Version:  2.0.40 2.2.26 2.4.37 2.6.39 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15

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

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