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
;
49 struct v4l2_subdev_format fmt
= {
50 .which
= V4L2_SUBDEV_FORMAT_ACTIVE
,
54 mutex_lock(&mdev
->mutex
);
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
);
62 void mxr_streamer_get(struct mxr_device
*mdev
)
64 mutex_lock(&mdev
->mutex
);
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
,
72 struct v4l2_mbus_framefmt
*mbus_fmt
= &fmt
.format
;
73 struct mxr_resources
*res
= &mdev
->res
;
76 if (to_output(mdev
)->cookie
== 0)
77 clk_set_parent(res
->sclk_mixer
, res
->sclk_dac
);
79 clk_set_parent(res
->sclk_mixer
, res
->sclk_hdmi
);
80 mxr_reg_s_output(mdev
, to_output(mdev
)->cookie
);
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
);
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
);
92 mutex_unlock(&mdev
->mutex
);
94 /* FIXME: what to do when streaming fails? */
97 void mxr_streamer_put(struct mxr_device
*mdev
)
99 mutex_lock(&mdev
->mutex
);
101 mxr_dbg(mdev
, "%s(%d)\n", __func__
, mdev
->n_streamer
);
102 if (mdev
->n_streamer
== 0) {
104 struct v4l2_subdev
*sd
= to_outsd(mdev
);
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
);
113 WARN(mdev
->n_streamer
< 0, "negative number of streamers (%d)\n",
115 mutex_unlock(&mdev
->mutex
);
119 void mxr_output_get(struct mxr_device
*mdev
)
121 mutex_lock(&mdev
->mutex
);
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
);
130 void mxr_output_put(struct mxr_device
*mdev
)
132 mutex_lock(&mdev
->mutex
);
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",
140 mutex_unlock(&mdev
->mutex
);
143 int mxr_power_get(struct mxr_device
*mdev
)
145 int ret
= pm_runtime_get_sync(mdev
->dev
);
147 /* returning 1 means that power is already enabled,
148 * so zero success be returned */
149 if (IS_ERR_VALUE(ret
))
154 void mxr_power_put(struct mxr_device
*mdev
)
156 pm_runtime_put_sync(mdev
->dev
);
159 /* --------- RESOURCE MANAGEMENT -------------*/
161 static int mxr_acquire_plat_resources(struct mxr_device
*mdev
,
162 struct platform_device
*pdev
)
164 struct resource
*res
;
167 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "mxr");
169 mxr_err(mdev
, "get memory resource failed.\n");
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");
181 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "vp");
183 mxr_err(mdev
, "get memory resource failed.\n");
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");
195 res
= platform_get_resource_byname(pdev
, IORESOURCE_IRQ
, "irq");
197 mxr_err(mdev
, "get interrupt resource failed.\n");
202 ret
= request_irq(res
->start
, mxr_irq_handler
, 0, "s5p-mixer", mdev
);
204 mxr_err(mdev
, "request interrupt failed.\n");
207 mdev
->res
.irq
= res
->start
;
212 iounmap(mdev
->res
.vp_regs
);
215 iounmap(mdev
->res
.mxr_regs
);
221 static void mxr_resource_clear_clocks(struct mxr_resources
*res
)
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
);
230 static void mxr_release_plat_resources(struct mxr_device
*mdev
)
232 free_irq(mdev
->res
.irq
, mdev
);
233 iounmap(mdev
->res
.vp_regs
);
234 iounmap(mdev
->res
.mxr_regs
);
237 static void mxr_release_clocks(struct mxr_device
*mdev
)
239 struct mxr_resources
*res
= &mdev
->res
;
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
))
249 if (!IS_ERR(res
->mixer
))
253 static int mxr_acquire_clocks(struct mxr_device
*mdev
)
255 struct mxr_resources
*res
= &mdev
->res
;
256 struct device
*dev
= mdev
->dev
;
258 mxr_resource_clear_clocks(res
);
260 res
->mixer
= clk_get(dev
, "mixer");
261 if (IS_ERR(res
->mixer
)) {
262 mxr_err(mdev
, "failed to get clock 'mixer'\n");
265 res
->vp
= clk_get(dev
, "vp");
266 if (IS_ERR(res
->vp
)) {
267 mxr_err(mdev
, "failed to get clock 'vp'\n");
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");
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");
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");
288 mxr_release_clocks(mdev
);
292 static int mxr_acquire_resources(struct mxr_device
*mdev
,
293 struct platform_device
*pdev
)
296 ret
= mxr_acquire_plat_resources(mdev
, pdev
);
301 ret
= mxr_acquire_clocks(mdev
);
305 mxr_info(mdev
, "resources acquired\n");
309 mxr_release_plat_resources(mdev
);
311 mxr_err(mdev
, "resources acquire failed\n");
315 static void mxr_release_resources(struct mxr_device
*mdev
)
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
);
323 static void mxr_release_layers(struct mxr_device
*mdev
)
327 for (i
= 0; i
< ARRAY_SIZE(mdev
->layer
); ++i
)
329 mxr_layer_release(mdev
->layer
[i
]);
332 static int mxr_acquire_layers(struct mxr_device
*mdev
,
333 struct mxr_platform_data
*pdata
)
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);
339 if (!mdev
->layer
[0] || !mdev
->layer
[1] || !mdev
->layer
[2]) {
340 mxr_err(mdev
, "failed to acquire layers\n");
347 mxr_release_layers(mdev
);
351 /* ---------- POWER MANAGEMENT ----------- */
353 static int mxr_runtime_resume(struct device
*dev
)
355 struct mxr_device
*mdev
= to_mdev(dev
);
356 struct mxr_resources
*res
= &mdev
->res
;
359 mxr_dbg(mdev
, "resume - start\n");
360 mutex_lock(&mdev
->mutex
);
362 ret
= clk_prepare_enable(res
->mixer
);
364 dev_err(mdev
->dev
, "clk_prepare_enable(mixer) failed\n");
367 ret
= clk_prepare_enable(res
->vp
);
369 dev_err(mdev
->dev
, "clk_prepare_enable(vp) failed\n");
372 ret
= clk_prepare_enable(res
->sclk_mixer
);
374 dev_err(mdev
->dev
, "clk_prepare_enable(sclk_mixer) failed\n");
377 /* apply default configuration */
379 mxr_dbg(mdev
, "resume - finished\n");
381 mutex_unlock(&mdev
->mutex
);
385 clk_disable_unprepare(res
->vp
);
387 clk_disable_unprepare(res
->mixer
);
389 mutex_unlock(&mdev
->mutex
);
390 dev_err(mdev
->dev
, "resume failed\n");
394 static int mxr_runtime_suspend(struct device
*dev
)
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");
409 static const struct dev_pm_ops mxr_pm_ops
= {
410 .runtime_suspend
= mxr_runtime_suspend
,
411 .runtime_resume
= mxr_runtime_resume
,
414 /* --------- DRIVER INITIALIZATION ---------- */
416 static int mxr_probe(struct platform_device
*pdev
)
418 struct device
*dev
= &pdev
->dev
;
419 struct mxr_platform_data
*pdata
= dev
->platform_data
;
420 struct mxr_device
*mdev
;
423 /* mdev does not exist yet so no mxr_dbg is used */
424 dev_info(dev
, "probe start\n");
426 mdev
= kzalloc(sizeof(*mdev
), GFP_KERNEL
);
428 dev_err(dev
, "not enough memory.\n");
433 /* setup pointer to master device */
436 mutex_init(&mdev
->mutex
);
437 spin_lock_init(&mdev
->reg_slock
);
438 init_waitqueue_head(&mdev
->event_queue
);
440 /* acquire resources: regs, irqs, clocks, regulators */
441 ret
= mxr_acquire_resources(mdev
, pdev
);
445 /* configure resources for video output */
446 ret
= mxr_acquire_video(mdev
, mxr_output_conf
,
447 ARRAY_SIZE(mxr_output_conf
));
451 /* configure layers */
452 ret
= mxr_acquire_layers(mdev
, pdata
);
456 pm_runtime_enable(dev
);
458 mxr_info(mdev
, "probe successful\n");
462 mxr_release_video(mdev
);
465 mxr_release_resources(mdev
);
471 dev_info(dev
, "probe failed\n");
475 static int mxr_remove(struct platform_device
*pdev
)
477 struct device
*dev
= &pdev
->dev
;
478 struct mxr_device
*mdev
= to_mdev(dev
);
480 pm_runtime_disable(dev
);
482 mxr_release_layers(mdev
);
483 mxr_release_video(mdev
);
484 mxr_release_resources(mdev
);
488 dev_info(dev
, "remove successful\n");
492 static struct platform_driver mxr_driver __refdata
= {
494 .remove
= mxr_remove
,
496 .name
= MXR_DRIVER_NAME
,
501 static int __init
mxr_init(void)
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
);
509 /* Loading auxiliary modules */
510 for (i
= 0; i
< ARRAY_SIZE(mxr_output_conf
); ++i
)
511 request_module(mxr_output_conf
[i
].module_name
);
513 ret
= platform_driver_register(&mxr_driver
);
515 pr_err("s5p-tv: registration of MIXER driver failed\n");
521 module_init(mxr_init
);
523 static void __exit
mxr_exit(void)
525 platform_driver_unregister(&mxr_driver
);
527 module_exit(mxr_exit
);