2 * Samsung TV Mixer driver
4 * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
6 * Tomasz Stanislawski, <t.stanislaws@samsung.com>
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
16 #include <linux/module.h>
17 #include <linux/platform_device.h>
19 #include <linux/interrupt.h>
20 #include <linux/irq.h>
22 #include <linux/delay.h>
23 #include <linux/pm_runtime.h>
24 #include <linux/clk.h>
26 MODULE_AUTHOR("Tomasz Stanislawski, <t.stanislaws@samsung.com>");
27 MODULE_DESCRIPTION("Samsung MIXER");
28 MODULE_LICENSE("GPL");
30 /* --------- DRIVER PARAMETERS ---------- */
32 static struct mxr_output_conf mxr_output_conf
[] = {
34 .output_name
= "S5P HDMI connector",
35 .module_name
= "s5p-hdmi",
39 .output_name
= "S5P SDO connector",
40 .module_name
= "s5p-sdo",
45 void mxr_get_mbus_fmt(struct mxr_device
*mdev
,
46 struct v4l2_mbus_framefmt
*mbus_fmt
)
48 struct v4l2_subdev
*sd
;
51 mutex_lock(&mdev
->mutex
);
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
);
58 void mxr_streamer_get(struct mxr_device
*mdev
)
60 mutex_lock(&mdev
->mutex
);
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
;
69 if (to_output(mdev
)->cookie
== 0)
70 clk_set_parent(res
->sclk_mixer
, res
->sclk_dac
);
72 clk_set_parent(res
->sclk_mixer
, res
->sclk_hdmi
);
73 mxr_reg_s_output(mdev
, to_output(mdev
)->cookie
);
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
);
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
);
85 mutex_unlock(&mdev
->mutex
);
87 /* FIXME: what to do when streaming fails? */
90 void mxr_streamer_put(struct mxr_device
*mdev
)
92 mutex_lock(&mdev
->mutex
);
94 mxr_dbg(mdev
, "%s(%d)\n", __func__
, mdev
->n_streamer
);
95 if (mdev
->n_streamer
== 0) {
97 struct v4l2_subdev
*sd
= to_outsd(mdev
);
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
);
106 WARN(mdev
->n_streamer
< 0, "negative number of streamers (%d)\n",
108 mutex_unlock(&mdev
->mutex
);
112 void mxr_output_get(struct mxr_device
*mdev
)
114 mutex_lock(&mdev
->mutex
);
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
);
123 void mxr_output_put(struct mxr_device
*mdev
)
125 mutex_lock(&mdev
->mutex
);
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",
133 mutex_unlock(&mdev
->mutex
);
136 int mxr_power_get(struct mxr_device
*mdev
)
138 int ret
= pm_runtime_get_sync(mdev
->dev
);
140 /* returning 1 means that power is already enabled,
141 * so zero success be returned */
142 if (IS_ERR_VALUE(ret
))
147 void mxr_power_put(struct mxr_device
*mdev
)
149 pm_runtime_put_sync(mdev
->dev
);
152 /* --------- RESOURCE MANAGEMENT -------------*/
154 static int __devinit
mxr_acquire_plat_resources(struct mxr_device
*mdev
,
155 struct platform_device
*pdev
)
157 struct resource
*res
;
160 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "mxr");
162 mxr_err(mdev
, "get memory resource failed.\n");
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");
174 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "vp");
176 mxr_err(mdev
, "get memory resource failed.\n");
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");
188 res
= platform_get_resource_byname(pdev
, IORESOURCE_IRQ
, "irq");
190 mxr_err(mdev
, "get interrupt resource failed.\n");
195 ret
= request_irq(res
->start
, mxr_irq_handler
, 0, "s5p-mixer", mdev
);
197 mxr_err(mdev
, "request interrupt failed.\n");
200 mdev
->res
.irq
= res
->start
;
205 iounmap(mdev
->res
.vp_regs
);
208 iounmap(mdev
->res
.mxr_regs
);
214 static void mxr_release_plat_resources(struct mxr_device
*mdev
)
216 free_irq(mdev
->res
.irq
, mdev
);
217 iounmap(mdev
->res
.vp_regs
);
218 iounmap(mdev
->res
.mxr_regs
);
221 static void mxr_release_clocks(struct mxr_device
*mdev
)
223 struct mxr_resources
*res
= &mdev
->res
;
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
))
233 if (!IS_ERR_OR_NULL(res
->mixer
))
237 static int mxr_acquire_clocks(struct mxr_device
*mdev
)
239 struct mxr_resources
*res
= &mdev
->res
;
240 struct device
*dev
= mdev
->dev
;
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");
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");
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");
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");
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");
270 mxr_release_clocks(mdev
);
274 static int __devinit
mxr_acquire_resources(struct mxr_device
*mdev
,
275 struct platform_device
*pdev
)
278 ret
= mxr_acquire_plat_resources(mdev
, pdev
);
283 ret
= mxr_acquire_clocks(mdev
);
287 mxr_info(mdev
, "resources acquired\n");
291 mxr_release_plat_resources(mdev
);
293 mxr_err(mdev
, "resources acquire failed\n");
297 static void mxr_release_resources(struct mxr_device
*mdev
)
299 mxr_release_clocks(mdev
);
300 mxr_release_plat_resources(mdev
);
301 memset(&mdev
->res
, 0, sizeof mdev
->res
);
304 static void mxr_release_layers(struct mxr_device
*mdev
)
308 for (i
= 0; i
< ARRAY_SIZE(mdev
->layer
); ++i
)
310 mxr_layer_release(mdev
->layer
[i
]);
313 static int __devinit
mxr_acquire_layers(struct mxr_device
*mdev
,
314 struct mxr_platform_data
*pdata
)
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);
320 if (!mdev
->layer
[0] || !mdev
->layer
[1] || !mdev
->layer
[2]) {
321 mxr_err(mdev
, "failed to acquire layers\n");
328 mxr_release_layers(mdev
);
332 /* ---------- POWER MANAGEMENT ----------- */
334 static int mxr_runtime_resume(struct device
*dev
)
336 struct mxr_device
*mdev
= to_mdev(dev
);
337 struct mxr_resources
*res
= &mdev
->res
;
339 mxr_dbg(mdev
, "resume - start\n");
340 mutex_lock(&mdev
->mutex
);
342 clk_enable(res
->mixer
);
344 clk_enable(res
->sclk_mixer
);
345 /* apply default configuration */
347 mxr_dbg(mdev
, "resume - finished\n");
349 mutex_unlock(&mdev
->mutex
);
353 static int mxr_runtime_suspend(struct device
*dev
)
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");
368 static const struct dev_pm_ops mxr_pm_ops
= {
369 .runtime_suspend
= mxr_runtime_suspend
,
370 .runtime_resume
= mxr_runtime_resume
,
373 /* --------- DRIVER INITIALIZATION ---------- */
375 static int __devinit
mxr_probe(struct platform_device
*pdev
)
377 struct device
*dev
= &pdev
->dev
;
378 struct mxr_platform_data
*pdata
= dev
->platform_data
;
379 struct mxr_device
*mdev
;
382 /* mdev does not exist yet so no mxr_dbg is used */
383 dev_info(dev
, "probe start\n");
385 mdev
= kzalloc(sizeof *mdev
, GFP_KERNEL
);
387 mxr_err(mdev
, "not enough memory.\n");
392 /* setup pointer to master device */
395 mutex_init(&mdev
->mutex
);
396 spin_lock_init(&mdev
->reg_slock
);
397 init_waitqueue_head(&mdev
->event_queue
);
399 /* acquire resources: regs, irqs, clocks, regulators */
400 ret
= mxr_acquire_resources(mdev
, pdev
);
404 /* configure resources for video output */
405 ret
= mxr_acquire_video(mdev
, mxr_output_conf
,
406 ARRAY_SIZE(mxr_output_conf
));
410 /* configure layers */
411 ret
= mxr_acquire_layers(mdev
, pdata
);
415 pm_runtime_enable(dev
);
417 mxr_info(mdev
, "probe successful\n");
421 mxr_release_video(mdev
);
424 mxr_release_resources(mdev
);
430 dev_info(dev
, "probe failed\n");
434 static int __devexit
mxr_remove(struct platform_device
*pdev
)
436 struct device
*dev
= &pdev
->dev
;
437 struct mxr_device
*mdev
= to_mdev(dev
);
439 pm_runtime_disable(dev
);
441 mxr_release_layers(mdev
);
442 mxr_release_video(mdev
);
443 mxr_release_resources(mdev
);
447 dev_info(dev
, "remove sucessful\n");
451 static struct platform_driver mxr_driver __refdata
= {
453 .remove
= __devexit_p(mxr_remove
),
455 .name
= MXR_DRIVER_NAME
,
456 .owner
= THIS_MODULE
,
461 static int __init
mxr_init(void)
464 static const char banner
[] __initdata
= KERN_INFO
465 "Samsung TV Mixer driver, "
466 "(c) 2010-2011 Samsung Electronics Co., Ltd.\n";
469 /* Loading auxiliary modules */
470 for (i
= 0; i
< ARRAY_SIZE(mxr_output_conf
); ++i
)
471 request_module(mxr_output_conf
[i
].module_name
);
473 ret
= platform_driver_register(&mxr_driver
);
475 printk(KERN_ERR
"registration of MIXER driver failed\n");
481 module_init(mxr_init
);
483 static void __exit
mxr_exit(void)
485 platform_driver_unregister(&mxr_driver
);
487 module_exit(mxr_exit
);