upload tizen1.0 source
[kernel/linux-2.6.36.git] / drivers / media / video / samsung / tvout / s5p_tvout_common_lib.c
1 /* linux/drivers/media/video/samsung/tvout/s5p_tvout_common_lib.c
2  *
3  * Copyright (c) 2009 Samsung Electronics
4  *              http://www.samsung.com/
5  *
6  * Common library file for SAMSUNG TVOUT driver
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  */
12
13 #include <linux/io.h>
14 #include <linux/slab.h>
15 #include <linux/err.h>
16
17 #include <linux/pm_runtime.h>
18
19 #include "s5p_tvout_common_lib.h"
20
21 #ifdef CONFIG_VCM
22 #include <plat/s5p-vcm.h>
23 #endif
24
25 #ifdef CONFIG_VCM
26 static atomic_t         s5p_tvout_vcm_usage = ATOMIC_INIT(0);
27
28 static void tvout_tlb_invalidator(enum vcm_dev_id id)
29 {
30 #if (defined(CONFIG_S5PV310_DEV_PD) && defined(CONFIG_PM_RUNTIME))
31         if (atomic_read(&s5p_tvout_vcm_usage) == 0) {
32                 return (void)0;
33         }
34 #endif
35 #ifdef CONFIG_S5P_SYSMMU_TV
36         sysmmu_tlb_invalidate(SYSMMU_TV);
37 #endif
38 }
39
40 static void tvout_pgd_base_specifier(enum vcm_dev_id id, unsigned long base)
41 {
42
43 #if (defined(CONFIG_S5PV310_DEV_PD) && defined(CONFIG_PM_RUNTIME))
44         if (atomic_read(&s5p_tvout_vcm_usage) == 0) {
45                 return (void)0;
46         }
47 #endif
48 #ifdef CONFIG_S5P_SYSMMU_TV
49         sysmmu_set_tablebase_pgd(SYSMMU_TV, base);
50 #endif
51 }
52
53 static struct s5p_vcm_driver s5ptv_vcm_driver = {
54         .tlb_invalidator = &tvout_tlb_invalidator,
55         .pgd_base_specifier = &tvout_pgd_base_specifier,
56         .phys_alloc = NULL,
57         .phys_free = NULL,
58 };
59
60 #endif
61
62
63 #ifdef CONFIG_VCM
64 static struct vcm       *s5p_vcm;
65
66 int s5p_tvout_vcm_create_unified(void)
67 {
68         s5p_vcm = vcm_create_unified((SZ_64M), VCM_DEV_TV,
69                                                 &s5ptv_vcm_driver);
70
71         if (IS_ERR(s5p_vcm))
72                 return PTR_ERR(s5p_vcm);
73
74         return 0;
75 }
76
77 int s5p_tvout_vcm_init(void)
78 {
79         if (vcm_activate(s5p_vcm) < 0)
80                 return -1;
81
82         return 0;
83 }
84
85 void s5p_tvout_vcm_activate(void)
86 {
87 #ifdef CONFIG_S5P_SYSMMU_TV
88         sysmmu_on(SYSMMU_TV);
89 #endif
90         vcm_set_pgtable_base(VCM_DEV_TV);
91 }
92
93 void s5p_tvout_vcm_deactivate(void)
94 {
95 #ifdef CONFIG_S5P_SYSMMU_TV
96         sysmmu_off(SYSMMU_TV);
97 #endif
98 }
99
100
101 #endif
102 int s5p_tvout_map_resource_mem(
103                 struct platform_device *pdev, char *name,
104                 void __iomem **base, struct resource **res)
105 {
106         size_t          size;
107         void __iomem    *tmp_base;
108         struct resource *tmp_res;
109
110         tmp_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
111
112         if (!tmp_res)
113                 goto not_found;
114
115         size = resource_size(tmp_res);
116
117         tmp_res = request_mem_region(tmp_res->start, size, tmp_res->name);
118
119         if (!tmp_res) {
120                 tvout_err("%s: fail to get memory region\n", __func__);
121                 goto err_on_request_mem_region;
122         }
123
124         tmp_base = ioremap(tmp_res->start, size);
125
126         if (!tmp_base) {
127                 tvout_err("%s: fail to ioremap address region\n", __func__);
128                 goto err_on_ioremap;
129         }
130
131         *res = tmp_res;
132         *base = tmp_base;
133         return 0;
134
135 err_on_ioremap:
136         release_resource(tmp_res);
137         kfree(tmp_res);
138
139 err_on_request_mem_region:
140         return -ENXIO;
141
142 not_found:
143         tvout_err("%s: fail to get IORESOURCE_MEM for %s\n", __func__, name);
144         return -ENODEV;
145 }
146
147 void s5p_tvout_unmap_resource_mem(
148                 void __iomem *base, struct resource *res)
149 {
150         if (!base)
151                 iounmap(base);
152
153         if (!res) {
154                 release_resource(res);
155                 kfree(res);
156         }
157 }
158
159 /* Libraries for runtime PM */
160 static struct device    *s5p_tvout_dev;
161
162
163 void s5p_tvout_pm_runtime_enable(struct device *dev)
164 {
165         pm_runtime_enable(dev);
166
167         s5p_tvout_dev = dev;
168 }
169
170 void s5p_tvout_pm_runtime_disable(struct device *dev)
171 {
172         pm_runtime_disable(dev);
173 }
174
175 void s5p_tvout_pm_runtime_get(void)
176 {
177         pm_runtime_get_sync(s5p_tvout_dev);
178
179 #ifdef CONFIG_VCM
180         atomic_inc(&s5p_tvout_vcm_usage);
181         if (atomic_read(&s5p_tvout_vcm_usage) == 1)
182                 s5p_tvout_vcm_activate();
183 #endif
184 }
185
186 void s5p_tvout_pm_runtime_put(void)
187 {
188 #ifdef CONFIG_VCM
189         if (atomic_read(&s5p_tvout_vcm_usage) == 1)
190                 s5p_tvout_vcm_deactivate();
191
192         atomic_dec(&s5p_tvout_vcm_usage);
193 #endif
194
195         pm_runtime_put_sync(s5p_tvout_dev);
196 }