aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/platform
diff options
context:
space:
mode:
authorSylwester Nawrocki <s.nawrocki@samsung.com>2013-03-21 13:43:17 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2013-03-31 09:58:46 -0400
commit056f4f3036394892ed591932326c11613b6584c1 (patch)
treefa84e249a5d7efad0d62cfdc945456d9370fa39d /drivers/media/platform
parent39bb6df6e35d406ccbe953f1595f650eb6bb88ce (diff)
[media] s5p-fimc: Add support for PIXELASYNCMx clocks
This patch ads handling of clocks for the CAMBLK subsystem which is a glue logic for FIMC-IS or LCD controller and FIMC IP. Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/platform')
-rw-r--r--drivers/media/platform/s5p-fimc/fimc-mdevice.c83
-rw-r--r--drivers/media/platform/s5p-fimc/fimc-mdevice.h10
2 files changed, 82 insertions, 11 deletions
diff --git a/drivers/media/platform/s5p-fimc/fimc-mdevice.c b/drivers/media/platform/s5p-fimc/fimc-mdevice.c
index 6972f52ba43f..c4a39782d55e 100644
--- a/drivers/media/platform/s5p-fimc/fimc-mdevice.c
+++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.c
@@ -151,26 +151,48 @@ static int fimc_pipeline_s_power(struct fimc_pipeline *p, bool state)
151 * __fimc_pipeline_open - update the pipeline information, enable power 151 * __fimc_pipeline_open - update the pipeline information, enable power
152 * of all pipeline subdevs and the sensor clock 152 * of all pipeline subdevs and the sensor clock
153 * @me: media entity to start graph walk with 153 * @me: media entity to start graph walk with
154 * @prep: true to acquire sensor (and csis) subdevs 154 * @prepare: true to walk the current pipeline and acquire all subdevs
155 * 155 *
156 * Called with the graph mutex held. 156 * Called with the graph mutex held.
157 */ 157 */
158static int __fimc_pipeline_open(struct fimc_pipeline *p, 158static int __fimc_pipeline_open(struct fimc_pipeline *p,
159 struct media_entity *me, bool prep) 159 struct media_entity *me, bool prepare)
160{ 160{
161 struct fimc_md *fmd = entity_to_fimc_mdev(me);
162 struct v4l2_subdev *sd;
161 int ret; 163 int ret;
162 164
163 if (prep) 165 if (WARN_ON(p == NULL || me == NULL))
166 return -EINVAL;
167
168 if (prepare)
164 fimc_pipeline_prepare(p, me); 169 fimc_pipeline_prepare(p, me);
165 170
166 if (p->subdevs[IDX_SENSOR] == NULL) 171 sd = p->subdevs[IDX_SENSOR];
172 if (sd == NULL)
167 return -EINVAL; 173 return -EINVAL;
168 174
169 ret = fimc_md_set_camclk(p->subdevs[IDX_SENSOR], true); 175 /* Disable PXLASYNC clock if this pipeline includes FIMC-IS */
170 if (ret) 176 if (!IS_ERR(fmd->wbclk[CLK_IDX_WB_B]) && p->subdevs[IDX_IS_ISP]) {
171 return ret; 177 ret = clk_prepare_enable(fmd->wbclk[CLK_IDX_WB_B]);
178 if (ret < 0)
179 return ret;
180 }
181 ret = fimc_md_set_camclk(sd, true);
182 if (ret < 0)
183 goto err_wbclk;
184
185 ret = fimc_pipeline_s_power(p, 1);
186 if (!ret)
187 return 0;
188
189 fimc_md_set_camclk(sd, false);
172 190
173 return fimc_pipeline_s_power(p, 1); 191err_wbclk:
192 if (!IS_ERR(fmd->wbclk[CLK_IDX_WB_B]) && p->subdevs[IDX_IS_ISP])
193 clk_disable_unprepare(fmd->wbclk[CLK_IDX_WB_B]);
194
195 return ret;
174} 196}
175 197
176/** 198/**
@@ -181,15 +203,24 @@ static int __fimc_pipeline_open(struct fimc_pipeline *p,
181 */ 203 */
182static int __fimc_pipeline_close(struct fimc_pipeline *p) 204static int __fimc_pipeline_close(struct fimc_pipeline *p)
183{ 205{
206 struct v4l2_subdev *sd = p ? p->subdevs[IDX_SENSOR] : NULL;
207 struct fimc_md *fmd;
184 int ret = 0; 208 int ret = 0;
185 209
186 if (!p || !p->subdevs[IDX_SENSOR]) 210 if (WARN_ON(sd == NULL))
187 return -EINVAL; 211 return -EINVAL;
188 212
189 if (p->subdevs[IDX_SENSOR]) { 213 if (p->subdevs[IDX_SENSOR]) {
190 ret = fimc_pipeline_s_power(p, 0); 214 ret = fimc_pipeline_s_power(p, 0);
191 fimc_md_set_camclk(p->subdevs[IDX_SENSOR], false); 215 fimc_md_set_camclk(sd, false);
192 } 216 }
217
218 fmd = entity_to_fimc_mdev(&sd->entity);
219
220 /* Disable PXLASYNC clock if this pipeline includes FIMC-IS */
221 if (!IS_ERR(fmd->wbclk[CLK_IDX_WB_B]) && p->subdevs[IDX_IS_ISP])
222 clk_disable_unprepare(fmd->wbclk[CLK_IDX_WB_B]);
223
193 return ret == -ENXIO ? 0 : ret; 224 return ret == -ENXIO ? 0 : ret;
194} 225}
195 226
@@ -959,7 +990,7 @@ static int fimc_md_create_links(struct fimc_md *fmd)
959} 990}
960 991
961/* 992/*
962 * The peripheral sensor clock management. 993 * The peripheral sensor and CAM_BLK (PIXELASYNCMx) clocks management.
963 */ 994 */
964static void fimc_md_put_clocks(struct fimc_md *fmd) 995static void fimc_md_put_clocks(struct fimc_md *fmd)
965{ 996{
@@ -972,6 +1003,14 @@ static void fimc_md_put_clocks(struct fimc_md *fmd)
972 clk_put(fmd->camclk[i].clock); 1003 clk_put(fmd->camclk[i].clock);
973 fmd->camclk[i].clock = ERR_PTR(-EINVAL); 1004 fmd->camclk[i].clock = ERR_PTR(-EINVAL);
974 } 1005 }
1006
1007 /* Writeback (PIXELASYNCMx) clocks */
1008 for (i = 0; i < FIMC_MAX_WBCLKS; i++) {
1009 if (IS_ERR(fmd->wbclk[i]))
1010 continue;
1011 clk_put(fmd->wbclk[i]);
1012 fmd->wbclk[i] = ERR_PTR(-EINVAL);
1013 }
975} 1014}
976 1015
977static int fimc_md_get_clocks(struct fimc_md *fmd) 1016static int fimc_md_get_clocks(struct fimc_md *fmd)
@@ -1008,6 +1047,28 @@ static int fimc_md_get_clocks(struct fimc_md *fmd)
1008 if (ret) 1047 if (ret)
1009 fimc_md_put_clocks(fmd); 1048 fimc_md_put_clocks(fmd);
1010 1049
1050 if (!fmd->use_isp)
1051 return 0;
1052 /*
1053 * For now get only PIXELASYNCM1 clock (Writeback B/ISP),
1054 * leave PIXELASYNCM0 out for the LCD Writeback driver.
1055 */
1056 fmd->wbclk[CLK_IDX_WB_A] = ERR_PTR(-EINVAL);
1057
1058 for (i = CLK_IDX_WB_B; i < FIMC_MAX_WBCLKS; i++) {
1059 snprintf(clk_name, sizeof(clk_name), "pxl_async%u", i);
1060 clock = clk_get(dev, clk_name);
1061 if (IS_ERR(clock)) {
1062 v4l2_err(&fmd->v4l2_dev, "Failed to get clock: %s\n",
1063 clk_name);
1064 ret = PTR_ERR(clock);
1065 break;
1066 }
1067 fmd->wbclk[i] = clock;
1068 }
1069 if (ret)
1070 fimc_md_put_clocks(fmd);
1071
1011 return ret; 1072 return ret;
1012} 1073}
1013 1074
diff --git a/drivers/media/platform/s5p-fimc/fimc-mdevice.h b/drivers/media/platform/s5p-fimc/fimc-mdevice.h
index 5d6146e76802..46f3b82e0446 100644
--- a/drivers/media/platform/s5p-fimc/fimc-mdevice.h
+++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.h
@@ -41,6 +41,13 @@
41#define FIMC_MAX_SENSORS 8 41#define FIMC_MAX_SENSORS 8
42#define FIMC_MAX_CAMCLKS 2 42#define FIMC_MAX_CAMCLKS 2
43 43
44/* LCD/ISP Writeback clocks (PIXELASYNCMx) */
45enum {
46 CLK_IDX_WB_A,
47 CLK_IDX_WB_B,
48 FIMC_MAX_WBCLKS
49};
50
44struct fimc_csis_info { 51struct fimc_csis_info {
45 struct v4l2_subdev *sd; 52 struct v4l2_subdev *sd;
46 int id; 53 int id;
@@ -73,6 +80,7 @@ struct fimc_sensor_info {
73 * @num_sensors: actual number of registered sensors 80 * @num_sensors: actual number of registered sensors
74 * @camclk: external sensor clock information 81 * @camclk: external sensor clock information
75 * @fimc: array of registered fimc devices 82 * @fimc: array of registered fimc devices
83 * @use_isp: set to true when FIMC-IS subsystem is used
76 * @media_dev: top level media device 84 * @media_dev: top level media device
77 * @v4l2_dev: top level v4l2_device holding up the subdevs 85 * @v4l2_dev: top level v4l2_device holding up the subdevs
78 * @pdev: platform device this media device is hooked up into 86 * @pdev: platform device this media device is hooked up into
@@ -87,8 +95,10 @@ struct fimc_md {
87 struct fimc_sensor_info sensor[FIMC_MAX_SENSORS]; 95 struct fimc_sensor_info sensor[FIMC_MAX_SENSORS];
88 int num_sensors; 96 int num_sensors;
89 struct fimc_camclk_info camclk[FIMC_MAX_CAMCLKS]; 97 struct fimc_camclk_info camclk[FIMC_MAX_CAMCLKS];
98 struct clk *wbclk[FIMC_MAX_WBCLKS];
90 struct fimc_lite *fimc_lite[FIMC_LITE_MAX_DEVS]; 99 struct fimc_lite *fimc_lite[FIMC_LITE_MAX_DEVS];
91 struct fimc_dev *fimc[FIMC_MAX_DEVS]; 100 struct fimc_dev *fimc[FIMC_MAX_DEVS];
101 bool use_isp;
92 struct media_device media_dev; 102 struct media_device media_dev;
93 struct v4l2_device v4l2_dev; 103 struct v4l2_device v4l2_dev;
94 struct platform_device *pdev; 104 struct platform_device *pdev;