Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[pandora-kernel.git] / drivers / media / video / 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 __devinit 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_release_plat_resources(struct mxr_device *mdev)
215 {
216         free_irq(mdev->res.irq, mdev);
217         iounmap(mdev->res.vp_regs);
218         iounmap(mdev->res.mxr_regs);
219 }
220
221 static void mxr_release_clocks(struct mxr_device *mdev)
222 {
223         struct mxr_resources *res = &mdev->res;
224
225         if (!IS_ERR_OR_NULL(res->sclk_dac))
226                 clk_put(res->sclk_dac);
227         if (!IS_ERR_OR_NULL(res->sclk_hdmi))
228                 clk_put(res->sclk_hdmi);
229         if (!IS_ERR_OR_NULL(res->sclk_mixer))
230                 clk_put(res->sclk_mixer);
231         if (!IS_ERR_OR_NULL(res->vp))
232                 clk_put(res->vp);
233         if (!IS_ERR_OR_NULL(res->mixer))
234                 clk_put(res->mixer);
235 }
236
237 static int mxr_acquire_clocks(struct mxr_device *mdev)
238 {
239         struct mxr_resources *res = &mdev->res;
240         struct device *dev = mdev->dev;
241
242         res->mixer = clk_get(dev, "mixer");
243         if (IS_ERR_OR_NULL(res->mixer)) {
244                 mxr_err(mdev, "failed to get clock 'mixer'\n");
245                 goto fail;
246         }
247         res->vp = clk_get(dev, "vp");
248         if (IS_ERR_OR_NULL(res->vp)) {
249                 mxr_err(mdev, "failed to get clock 'vp'\n");
250                 goto fail;
251         }
252         res->sclk_mixer = clk_get(dev, "sclk_mixer");
253         if (IS_ERR_OR_NULL(res->sclk_mixer)) {
254                 mxr_err(mdev, "failed to get clock 'sclk_mixer'\n");
255                 goto fail;
256         }
257         res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
258         if (IS_ERR_OR_NULL(res->sclk_hdmi)) {
259                 mxr_err(mdev, "failed to get clock 'sclk_hdmi'\n");
260                 goto fail;
261         }
262         res->sclk_dac = clk_get(dev, "sclk_dac");
263         if (IS_ERR_OR_NULL(res->sclk_dac)) {
264                 mxr_err(mdev, "failed to get clock 'sclk_dac'\n");
265                 goto fail;
266         }
267
268         return 0;
269 fail:
270         mxr_release_clocks(mdev);
271         return -ENODEV;
272 }
273
274 static int __devinit mxr_acquire_resources(struct mxr_device *mdev,
275         struct platform_device *pdev)
276 {
277         int ret;
278         ret = mxr_acquire_plat_resources(mdev, pdev);
279
280         if (ret)
281                 goto fail;
282
283         ret = mxr_acquire_clocks(mdev);
284         if (ret)
285                 goto fail_plat;
286
287         mxr_info(mdev, "resources acquired\n");
288         return 0;
289
290 fail_plat:
291         mxr_release_plat_resources(mdev);
292 fail:
293         mxr_err(mdev, "resources acquire failed\n");
294         return ret;
295 }
296
297 static void mxr_release_resources(struct mxr_device *mdev)
298 {
299         mxr_release_clocks(mdev);
300         mxr_release_plat_resources(mdev);
301         memset(&mdev->res, 0, sizeof mdev->res);
302 }
303
304 static void mxr_release_layers(struct mxr_device *mdev)
305 {
306         int i;
307
308         for (i = 0; i < ARRAY_SIZE(mdev->layer); ++i)
309                 if (mdev->layer[i])
310                         mxr_layer_release(mdev->layer[i]);
311 }
312
313 static int __devinit mxr_acquire_layers(struct mxr_device *mdev,
314         struct mxr_platform_data *pdata)
315 {
316         mdev->layer[0] = mxr_graph_layer_create(mdev, 0);
317         mdev->layer[1] = mxr_graph_layer_create(mdev, 1);
318         mdev->layer[2] = mxr_vp_layer_create(mdev, 0);
319
320         if (!mdev->layer[0] || !mdev->layer[1] || !mdev->layer[2]) {
321                 mxr_err(mdev, "failed to acquire layers\n");
322                 goto fail;
323         }
324
325         return 0;
326
327 fail:
328         mxr_release_layers(mdev);
329         return -ENODEV;
330 }
331
332 /* ---------- POWER MANAGEMENT ----------- */
333
334 static int mxr_runtime_resume(struct device *dev)
335 {
336         struct mxr_device *mdev = to_mdev(dev);
337         struct mxr_resources *res = &mdev->res;
338
339         mxr_dbg(mdev, "resume - start\n");
340         mutex_lock(&mdev->mutex);
341         /* turn clocks on */
342         clk_enable(res->mixer);
343         clk_enable(res->vp);
344         clk_enable(res->sclk_mixer);
345         /* apply default configuration */
346         mxr_reg_reset(mdev);
347         mxr_dbg(mdev, "resume - finished\n");
348
349         mutex_unlock(&mdev->mutex);
350         return 0;
351 }
352
353 static int mxr_runtime_suspend(struct device *dev)
354 {
355         struct mxr_device *mdev = to_mdev(dev);
356         struct mxr_resources *res = &mdev->res;
357         mxr_dbg(mdev, "suspend - start\n");
358         mutex_lock(&mdev->mutex);
359         /* turn clocks off */
360         clk_disable(res->sclk_mixer);
361         clk_disable(res->vp);
362         clk_disable(res->mixer);
363         mutex_unlock(&mdev->mutex);
364         mxr_dbg(mdev, "suspend - finished\n");
365         return 0;
366 }
367
368 static const struct dev_pm_ops mxr_pm_ops = {
369         .runtime_suspend = mxr_runtime_suspend,
370         .runtime_resume  = mxr_runtime_resume,
371 };
372
373 /* --------- DRIVER INITIALIZATION ---------- */
374
375 static int __devinit mxr_probe(struct platform_device *pdev)
376 {
377         struct device *dev = &pdev->dev;
378         struct mxr_platform_data *pdata = dev->platform_data;
379         struct mxr_device *mdev;
380         int ret;
381
382         /* mdev does not exist yet so no mxr_dbg is used */
383         dev_info(dev, "probe start\n");
384
385         mdev = kzalloc(sizeof *mdev, GFP_KERNEL);
386         if (!mdev) {
387                 mxr_err(mdev, "not enough memory.\n");
388                 ret = -ENOMEM;
389                 goto fail;
390         }
391
392         /* setup pointer to master device */
393         mdev->dev = dev;
394
395         mutex_init(&mdev->mutex);
396         spin_lock_init(&mdev->reg_slock);
397         init_waitqueue_head(&mdev->event_queue);
398
399         /* acquire resources: regs, irqs, clocks, regulators */
400         ret = mxr_acquire_resources(mdev, pdev);
401         if (ret)
402                 goto fail_mem;
403
404         /* configure resources for video output */
405         ret = mxr_acquire_video(mdev, mxr_output_conf,
406                 ARRAY_SIZE(mxr_output_conf));
407         if (ret)
408                 goto fail_resources;
409
410         /* configure layers */
411         ret = mxr_acquire_layers(mdev, pdata);
412         if (ret)
413                 goto fail_video;
414
415         pm_runtime_enable(dev);
416
417         mxr_info(mdev, "probe successful\n");
418         return 0;
419
420 fail_video:
421         mxr_release_video(mdev);
422
423 fail_resources:
424         mxr_release_resources(mdev);
425
426 fail_mem:
427         kfree(mdev);
428
429 fail:
430         dev_info(dev, "probe failed\n");
431         return ret;
432 }
433
434 static int __devexit mxr_remove(struct platform_device *pdev)
435 {
436         struct device *dev = &pdev->dev;
437         struct mxr_device *mdev = to_mdev(dev);
438
439         pm_runtime_disable(dev);
440
441         mxr_release_layers(mdev);
442         mxr_release_video(mdev);
443         mxr_release_resources(mdev);
444
445         kfree(mdev);
446
447         dev_info(dev, "remove sucessful\n");
448         return 0;
449 }
450
451 static struct platform_driver mxr_driver __refdata = {
452         .probe = mxr_probe,
453         .remove = __devexit_p(mxr_remove),
454         .driver = {
455                 .name = MXR_DRIVER_NAME,
456                 .owner = THIS_MODULE,
457                 .pm = &mxr_pm_ops,
458         }
459 };
460
461 static int __init mxr_init(void)
462 {
463         int i, ret;
464         static const char banner[] __initdata = KERN_INFO
465                 "Samsung TV Mixer driver, "
466                 "(c) 2010-2011 Samsung Electronics Co., Ltd.\n";
467         printk(banner);
468
469         /* Loading auxiliary modules */
470         for (i = 0; i < ARRAY_SIZE(mxr_output_conf); ++i)
471                 request_module(mxr_output_conf[i].module_name);
472
473         ret = platform_driver_register(&mxr_driver);
474         if (ret != 0) {
475                 printk(KERN_ERR "registration of MIXER driver failed\n");
476                 return -ENXIO;
477         }
478
479         return 0;
480 }
481 module_init(mxr_init);
482
483 static void __exit mxr_exit(void)
484 {
485         platform_driver_unregister(&mxr_driver);
486 }
487 module_exit(mxr_exit);