Version:  2.0.40 2.2.26 2.4.37 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1 4.2

Linux/drivers/media/platform/s5p-tv/mixer_drv.c

  1 /*
  2  * Samsung TV Mixer driver
  3  *
  4  * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
  5  *
  6  * Tomasz Stanislawski, <t.stanislaws@samsung.com>
  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 as published
 10  * by the Free Software Foundiation. either version 2 of the License,
 11  * or (at your option) any later version
 12  */
 13 
 14 #include "mixer.h"
 15 
 16 #include <linux/module.h>
 17 #include <linux/platform_device.h>
 18 #include <linux/io.h>
 19 #include <linux/interrupt.h>
 20 #include <linux/irq.h>
 21 #include <linux/fb.h>
 22 #include <linux/delay.h>
 23 #include <linux/pm_runtime.h>
 24 #include <linux/clk.h>
 25 
 26 MODULE_AUTHOR("Tomasz Stanislawski, <t.stanislaws@samsung.com>");
 27 MODULE_DESCRIPTION("Samsung MIXER");
 28 MODULE_LICENSE("GPL");
 29 
 30 /* --------- DRIVER PARAMETERS ---------- */
 31 
 32 static struct mxr_output_conf mxr_output_conf[] = {
 33         {
 34                 .output_name = "S5P HDMI connector",
 35                 .module_name = "s5p-hdmi",
 36                 .cookie = 1,
 37         },
 38         {
 39                 .output_name = "S5P SDO connector",
 40                 .module_name = "s5p-sdo",
 41                 .cookie = 0,
 42         },
 43 };
 44 
 45 void mxr_get_mbus_fmt(struct mxr_device *mdev,
 46         struct v4l2_mbus_framefmt *mbus_fmt)
 47 {
 48         struct v4l2_subdev *sd;
 49         struct v4l2_subdev_format fmt = {
 50                 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
 51         };
 52         int ret;
 53 
 54         mutex_lock(&mdev->mutex);
 55         sd = to_outsd(mdev);
 56         ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
 57         *mbus_fmt = fmt.format;
 58         WARN(ret, "failed to get mbus_fmt for output %s\n", sd->name);
 59         mutex_unlock(&mdev->mutex);
 60 }
 61 
 62 void mxr_streamer_get(struct mxr_device *mdev)
 63 {
 64         mutex_lock(&mdev->mutex);
 65         ++mdev->n_streamer;
 66         mxr_dbg(mdev, "%s(%d)\n", __func__, mdev->n_streamer);
 67         if (mdev->n_streamer == 1) {
 68                 struct v4l2_subdev *sd = to_outsd(mdev);
 69                 struct v4l2_subdev_format fmt = {
 70                         .which = V4L2_SUBDEV_FORMAT_ACTIVE,
 71                 };
 72                 struct v4l2_mbus_framefmt *mbus_fmt = &fmt.format;
 73                 struct mxr_resources *res = &mdev->res;
 74                 int ret;
 75 
 76                 if (to_output(mdev)->cookie == 0)
 77                         clk_set_parent(res->sclk_mixer, res->sclk_dac);
 78                 else
 79                         clk_set_parent(res->sclk_mixer, res->sclk_hdmi);
 80                 mxr_reg_s_output(mdev, to_output(mdev)->cookie);
 81 
 82                 ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
 83                 WARN(ret, "failed to get mbus_fmt for output %s\n", sd->name);
 84                 ret = v4l2_subdev_call(sd, video, s_stream, 1);
 85                 WARN(ret, "starting stream failed for output %s\n", sd->name);
 86 
 87                 mxr_reg_set_mbus_fmt(mdev, mbus_fmt);
 88                 mxr_reg_streamon(mdev);
 89                 ret = mxr_reg_wait4vsync(mdev);
 90                 WARN(ret, "failed to get vsync (%d) from output\n", ret);
 91         }
 92         mutex_unlock(&mdev->mutex);
 93         mxr_reg_dump(mdev);
 94         /* FIXME: what to do when streaming fails? */
 95 }
 96 
 97 void mxr_streamer_put(struct mxr_device *mdev)
 98 {
 99         mutex_lock(&mdev->mutex);
100         --mdev->n_streamer;
101         mxr_dbg(mdev, "%s(%d)\n", __func__, mdev->n_streamer);
102         if (mdev->n_streamer == 0) {
103                 int ret;
104                 struct v4l2_subdev *sd = to_outsd(mdev);
105 
106                 mxr_reg_streamoff(mdev);
107                 /* vsync applies Mixer setup */
108                 ret = mxr_reg_wait4vsync(mdev);
109                 WARN(ret, "failed to get vsync (%d) from output\n", ret);
110                 ret = v4l2_subdev_call(sd, video, s_stream, 0);
111                 WARN(ret, "stopping stream failed for output %s\n", sd->name);
112         }
113         WARN(mdev->n_streamer < 0, "negative number of streamers (%d)\n",
114                 mdev->n_streamer);
115         mutex_unlock(&mdev->mutex);
116         mxr_reg_dump(mdev);
117 }
118 
119 void mxr_output_get(struct mxr_device *mdev)
120 {
121         mutex_lock(&mdev->mutex);
122         ++mdev->n_output;
123         mxr_dbg(mdev, "%s(%d)\n", __func__, mdev->n_output);
124         /* turn on auxiliary driver */
125         if (mdev->n_output == 1)
126                 v4l2_subdev_call(to_outsd(mdev), core, s_power, 1);
127         mutex_unlock(&mdev->mutex);
128 }
129 
130 void mxr_output_put(struct mxr_device *mdev)
131 {
132         mutex_lock(&mdev->mutex);
133         --mdev->n_output;
134         mxr_dbg(mdev, "%s(%d)\n", __func__, mdev->n_output);
135         /* turn on auxiliary driver */
136         if (mdev->n_output == 0)
137                 v4l2_subdev_call(to_outsd(mdev), core, s_power, 0);
138         WARN(mdev->n_output < 0, "negative number of output users (%d)\n",
139                 mdev->n_output);
140         mutex_unlock(&mdev->mutex);
141 }
142 
143 int mxr_power_get(struct mxr_device *mdev)
144 {
145         int ret = pm_runtime_get_sync(mdev->dev);
146 
147         /* returning 1 means that power is already enabled,
148          * so zero success be returned */
149         if (IS_ERR_VALUE(ret))
150                 return ret;
151         return 0;
152 }
153 
154 void mxr_power_put(struct mxr_device *mdev)
155 {
156         pm_runtime_put_sync(mdev->dev);
157 }
158 
159 /* --------- RESOURCE MANAGEMENT -------------*/
160 
161 static int mxr_acquire_plat_resources(struct mxr_device *mdev,
162                                       struct platform_device *pdev)
163 {
164         struct resource *res;
165         int ret;
166 
167         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mxr");
168         if (res == NULL) {
169                 mxr_err(mdev, "get memory resource failed.\n");
170                 ret = -ENXIO;
171                 goto fail;
172         }
173 
174         mdev->res.mxr_regs = ioremap(res->start, resource_size(res));
175         if (mdev->res.mxr_regs == NULL) {
176                 mxr_err(mdev, "register mapping failed.\n");
177                 ret = -ENXIO;
178                 goto fail;
179         }
180 
181         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vp");
182         if (res == NULL) {
183                 mxr_err(mdev, "get memory resource failed.\n");
184                 ret = -ENXIO;
185                 goto fail_mxr_regs;
186         }
187 
188         mdev->res.vp_regs = ioremap(res->start, resource_size(res));
189         if (mdev->res.vp_regs == NULL) {
190                 mxr_err(mdev, "register mapping failed.\n");
191                 ret = -ENXIO;
192                 goto fail_mxr_regs;
193         }
194 
195         res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq");
196         if (res == NULL) {
197                 mxr_err(mdev, "get interrupt resource failed.\n");
198                 ret = -ENXIO;
199                 goto fail_vp_regs;
200         }
201 
202         ret = request_irq(res->start, mxr_irq_handler, 0, "s5p-mixer", mdev);
203         if (ret) {
204                 mxr_err(mdev, "request interrupt failed.\n");
205                 goto fail_vp_regs;
206         }
207         mdev->res.irq = res->start;
208 
209         return 0;
210 
211 fail_vp_regs:
212         iounmap(mdev->res.vp_regs);
213 
214 fail_mxr_regs:
215         iounmap(mdev->res.mxr_regs);
216 
217 fail:
218         return ret;
219 }
220 
221 static void mxr_resource_clear_clocks(struct mxr_resources *res)
222 {
223         res->mixer      = ERR_PTR(-EINVAL);
224         res->vp         = ERR_PTR(-EINVAL);
225         res->sclk_mixer = ERR_PTR(-EINVAL);
226         res->sclk_hdmi  = ERR_PTR(-EINVAL);
227         res->sclk_dac   = ERR_PTR(-EINVAL);
228 }
229 
230 static void mxr_release_plat_resources(struct mxr_device *mdev)
231 {
232         free_irq(mdev->res.irq, mdev);
233         iounmap(mdev->res.vp_regs);
234         iounmap(mdev->res.mxr_regs);
235 }
236 
237 static void mxr_release_clocks(struct mxr_device *mdev)
238 {
239         struct mxr_resources *res = &mdev->res;
240 
241         if (!IS_ERR(res->sclk_dac))
242                 clk_put(res->sclk_dac);
243         if (!IS_ERR(res->sclk_hdmi))
244                 clk_put(res->sclk_hdmi);
245         if (!IS_ERR(res->sclk_mixer))
246                 clk_put(res->sclk_mixer);
247         if (!IS_ERR(res->vp))
248                 clk_put(res->vp);
249         if (!IS_ERR(res->mixer))
250                 clk_put(res->mixer);
251 }
252 
253 static int mxr_acquire_clocks(struct mxr_device *mdev)
254 {
255         struct mxr_resources *res = &mdev->res;
256         struct device *dev = mdev->dev;
257 
258         mxr_resource_clear_clocks(res);
259 
260         res->mixer = clk_get(dev, "mixer");
261         if (IS_ERR(res->mixer)) {
262                 mxr_err(mdev, "failed to get clock 'mixer'\n");
263                 goto fail;
264         }
265         res->vp = clk_get(dev, "vp");
266         if (IS_ERR(res->vp)) {
267                 mxr_err(mdev, "failed to get clock 'vp'\n");
268                 goto fail;
269         }
270         res->sclk_mixer = clk_get(dev, "sclk_mixer");
271         if (IS_ERR(res->sclk_mixer)) {
272                 mxr_err(mdev, "failed to get clock 'sclk_mixer'\n");
273                 goto fail;
274         }
275         res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
276         if (IS_ERR(res->sclk_hdmi)) {
277                 mxr_err(mdev, "failed to get clock 'sclk_hdmi'\n");
278                 goto fail;
279         }
280         res->sclk_dac = clk_get(dev, "sclk_dac");
281         if (IS_ERR(res->sclk_dac)) {
282                 mxr_err(mdev, "failed to get clock 'sclk_dac'\n");
283                 goto fail;
284         }
285 
286         return 0;
287 fail:
288         mxr_release_clocks(mdev);
289         return -ENODEV;
290 }
291 
292 static int mxr_acquire_resources(struct mxr_device *mdev,
293                                  struct platform_device *pdev)
294 {
295         int ret;
296         ret = mxr_acquire_plat_resources(mdev, pdev);
297 
298         if (ret)
299                 goto fail;
300 
301         ret = mxr_acquire_clocks(mdev);
302         if (ret)
303                 goto fail_plat;
304 
305         mxr_info(mdev, "resources acquired\n");
306         return 0;
307 
308 fail_plat:
309         mxr_release_plat_resources(mdev);
310 fail:
311         mxr_err(mdev, "resources acquire failed\n");
312         return ret;
313 }
314 
315 static void mxr_release_resources(struct mxr_device *mdev)
316 {
317         mxr_release_clocks(mdev);
318         mxr_release_plat_resources(mdev);
319         memset(&mdev->res, 0, sizeof(mdev->res));
320         mxr_resource_clear_clocks(&mdev->res);
321 }
322 
323 static void mxr_release_layers(struct mxr_device *mdev)
324 {
325         int i;
326 
327         for (i = 0; i < ARRAY_SIZE(mdev->layer); ++i)
328                 if (mdev->layer[i])
329                         mxr_layer_release(mdev->layer[i]);
330 }
331 
332 static int mxr_acquire_layers(struct mxr_device *mdev,
333                               struct mxr_platform_data *pdata)
334 {
335         mdev->layer[0] = mxr_graph_layer_create(mdev, 0);
336         mdev->layer[1] = mxr_graph_layer_create(mdev, 1);
337         mdev->layer[2] = mxr_vp_layer_create(mdev, 0);
338 
339         if (!mdev->layer[0] || !mdev->layer[1] || !mdev->layer[2]) {
340                 mxr_err(mdev, "failed to acquire layers\n");
341                 goto fail;
342         }
343 
344         return 0;
345 
346 fail:
347         mxr_release_layers(mdev);
348         return -ENODEV;
349 }
350 
351 /* ---------- POWER MANAGEMENT ----------- */
352 
353 static int mxr_runtime_resume(struct device *dev)
354 {
355         struct mxr_device *mdev = to_mdev(dev);
356         struct mxr_resources *res = &mdev->res;
357         int ret;
358 
359         mxr_dbg(mdev, "resume - start\n");
360         mutex_lock(&mdev->mutex);
361         /* turn clocks on */
362         ret = clk_prepare_enable(res->mixer);
363         if (ret < 0) {
364                 dev_err(mdev->dev, "clk_prepare_enable(mixer) failed\n");
365                 goto fail;
366         }
367         ret = clk_prepare_enable(res->vp);
368         if (ret < 0) {
369                 dev_err(mdev->dev, "clk_prepare_enable(vp) failed\n");
370                 goto fail_mixer;
371         }
372         ret = clk_prepare_enable(res->sclk_mixer);
373         if (ret < 0) {
374                 dev_err(mdev->dev, "clk_prepare_enable(sclk_mixer) failed\n");
375                 goto fail_vp;
376         }
377         /* apply default configuration */
378         mxr_reg_reset(mdev);
379         mxr_dbg(mdev, "resume - finished\n");
380 
381         mutex_unlock(&mdev->mutex);
382         return 0;
383 
384 fail_vp:
385         clk_disable_unprepare(res->vp);
386 fail_mixer:
387         clk_disable_unprepare(res->mixer);
388 fail:
389         mutex_unlock(&mdev->mutex);
390         dev_err(mdev->dev, "resume failed\n");
391         return ret;
392 }
393 
394 static int mxr_runtime_suspend(struct device *dev)
395 {
396         struct mxr_device *mdev = to_mdev(dev);
397         struct mxr_resources *res = &mdev->res;
398         mxr_dbg(mdev, "suspend - start\n");
399         mutex_lock(&mdev->mutex);
400         /* turn clocks off */
401         clk_disable_unprepare(res->sclk_mixer);
402         clk_disable_unprepare(res->vp);
403         clk_disable_unprepare(res->mixer);
404         mutex_unlock(&mdev->mutex);
405         mxr_dbg(mdev, "suspend - finished\n");
406         return 0;
407 }
408 
409 static const struct dev_pm_ops mxr_pm_ops = {
410         .runtime_suspend = mxr_runtime_suspend,
411         .runtime_resume  = mxr_runtime_resume,
412 };
413 
414 /* --------- DRIVER INITIALIZATION ---------- */
415 
416 static int mxr_probe(struct platform_device *pdev)
417 {
418         struct device *dev = &pdev->dev;
419         struct mxr_platform_data *pdata = dev->platform_data;
420         struct mxr_device *mdev;
421         int ret;
422 
423         /* mdev does not exist yet so no mxr_dbg is used */
424         dev_info(dev, "probe start\n");
425 
426         mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
427         if (!mdev) {
428                 dev_err(dev, "not enough memory.\n");
429                 ret = -ENOMEM;
430                 goto fail;
431         }
432 
433         /* setup pointer to master device */
434         mdev->dev = dev;
435 
436         mutex_init(&mdev->mutex);
437         spin_lock_init(&mdev->reg_slock);
438         init_waitqueue_head(&mdev->event_queue);
439 
440         /* acquire resources: regs, irqs, clocks, regulators */
441         ret = mxr_acquire_resources(mdev, pdev);
442         if (ret)
443                 goto fail_mem;
444 
445         /* configure resources for video output */
446         ret = mxr_acquire_video(mdev, mxr_output_conf,
447                 ARRAY_SIZE(mxr_output_conf));
448         if (ret)
449                 goto fail_resources;
450 
451         /* configure layers */
452         ret = mxr_acquire_layers(mdev, pdata);
453         if (ret)
454                 goto fail_video;
455 
456         pm_runtime_enable(dev);
457 
458         mxr_info(mdev, "probe successful\n");
459         return 0;
460 
461 fail_video:
462         mxr_release_video(mdev);
463 
464 fail_resources:
465         mxr_release_resources(mdev);
466 
467 fail_mem:
468         kfree(mdev);
469 
470 fail:
471         dev_info(dev, "probe failed\n");
472         return ret;
473 }
474 
475 static int mxr_remove(struct platform_device *pdev)
476 {
477         struct device *dev = &pdev->dev;
478         struct mxr_device *mdev = to_mdev(dev);
479 
480         pm_runtime_disable(dev);
481 
482         mxr_release_layers(mdev);
483         mxr_release_video(mdev);
484         mxr_release_resources(mdev);
485 
486         kfree(mdev);
487 
488         dev_info(dev, "remove successful\n");
489         return 0;
490 }
491 
492 static struct platform_driver mxr_driver __refdata = {
493         .probe = mxr_probe,
494         .remove = mxr_remove,
495         .driver = {
496                 .name = MXR_DRIVER_NAME,
497                 .pm = &mxr_pm_ops,
498         }
499 };
500 
501 static int __init mxr_init(void)
502 {
503         int i, ret;
504         static const char banner[] __initconst =
505                 "Samsung TV Mixer driver, "
506                 "(c) 2010-2011 Samsung Electronics Co., Ltd.\n";
507         pr_info("%s\n", banner);
508 
509         /* Loading auxiliary modules */
510         for (i = 0; i < ARRAY_SIZE(mxr_output_conf); ++i)
511                 request_module(mxr_output_conf[i].module_name);
512 
513         ret = platform_driver_register(&mxr_driver);
514         if (ret != 0) {
515                 pr_err("s5p-tv: registration of MIXER driver failed\n");
516                 return -ENXIO;
517         }
518 
519         return 0;
520 }
521 module_init(mxr_init);
522 
523 static void __exit mxr_exit(void)
524 {
525         platform_driver_unregister(&mxr_driver);
526 }
527 module_exit(mxr_exit);
528 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us