• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
mxr_get_mbus_fmt(struct mxr_device * mdev,struct v4l2_mbus_framefmt * mbus_fmt)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 
mxr_streamer_get(struct mxr_device * mdev)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 
mxr_streamer_put(struct mxr_device * mdev)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 
mxr_output_get(struct mxr_device * mdev)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 
mxr_output_put(struct mxr_device * mdev)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 
mxr_power_get(struct mxr_device * mdev)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 
mxr_power_put(struct mxr_device * mdev)147 void mxr_power_put(struct mxr_device *mdev)
148 {
149 	pm_runtime_put_sync(mdev->dev);
150 }
151 
152 /* --------- RESOURCE MANAGEMENT -------------*/
153 
mxr_acquire_plat_resources(struct mxr_device * mdev,struct platform_device * pdev)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 
mxr_resource_clear_clocks(struct mxr_resources * res)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 
mxr_release_plat_resources(struct mxr_device * mdev)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 
mxr_release_clocks(struct mxr_device * mdev)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 
mxr_acquire_clocks(struct mxr_device * mdev)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 
mxr_acquire_resources(struct mxr_device * mdev,struct platform_device * pdev)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 
mxr_release_resources(struct mxr_device * mdev)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 
mxr_release_layers(struct mxr_device * mdev)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 
mxr_acquire_layers(struct mxr_device * mdev,struct mxr_platform_data * pdata)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 
mxr_runtime_resume(struct device * dev)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 
mxr_runtime_suspend(struct device * dev)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 
mxr_probe(struct platform_device * pdev)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 
mxr_remove(struct platform_device * pdev)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 
mxr_init(void)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 
mxr_exit(void)517 static void __exit mxr_exit(void)
518 {
519 	platform_driver_unregister(&mxr_driver);
520 }
521 module_exit(mxr_exit);
522