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
26MODULE_AUTHOR("Tomasz Stanislawski, <t.stanislaws@samsung.com>");
27MODULE_DESCRIPTION("Samsung MIXER");
28MODULE_LICENSE("GPL");
29
30/* --------- DRIVER PARAMETERS ---------- */
31
32static 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
45void 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
58void 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
90void 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
112void 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
123void 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
136int 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
147void mxr_power_put(struct mxr_device *mdev)
148{
149	pm_runtime_put_sync(mdev->dev);
150}
151
152/* --------- RESOURCE MANAGEMENT -------------*/
153
154static 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
204fail_vp_regs:
205	iounmap(mdev->res.vp_regs);
206
207fail_mxr_regs:
208	iounmap(mdev->res.mxr_regs);
209
210fail:
211	return ret;
212}
213
214static 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
223static 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
230static 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
246static 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;
280fail:
281	mxr_release_clocks(mdev);
282	return -ENODEV;
283}
284
285static 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
301fail_plat:
302	mxr_release_plat_resources(mdev);
303fail:
304	mxr_err(mdev, "resources acquire failed\n");
305	return ret;
306}
307
308static 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
316static 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
325static 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
339fail:
340	mxr_release_layers(mdev);
341	return -ENODEV;
342}
343
344/* ---------- POWER MANAGEMENT ----------- */
345
346static 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
377fail_vp:
378	clk_disable_unprepare(res->vp);
379fail_mixer:
380	clk_disable_unprepare(res->mixer);
381fail:
382	mutex_unlock(&mdev->mutex);
383	dev_err(mdev->dev, "resume failed\n");
384	return ret;
385}
386
387static 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
402static 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
409static 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
454fail_video:
455	mxr_release_video(mdev);
456
457fail_resources:
458	mxr_release_resources(mdev);
459
460fail_mem:
461	kfree(mdev);
462
463fail:
464	dev_info(dev, "probe failed\n");
465	return ret;
466}
467
468static 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
485static struct platform_driver mxr_driver __refdata = {
486	.probe = mxr_probe,
487	.remove = mxr_remove,
488	.driver = {
489		.name = MXR_DRIVER_NAME,
490		.pm = &mxr_pm_ops,
491	}
492};
493
494static int __init mxr_init(void)
495{
496	int i, ret;
497	static const char banner[] __initconst =
498		"Samsung TV Mixer driver, "
499		"(c) 2010-2011 Samsung Electronics Co., Ltd.\n";
500	pr_info("%s\n", banner);
501
502	/* Loading auxiliary modules */
503	for (i = 0; i < ARRAY_SIZE(mxr_output_conf); ++i)
504		request_module(mxr_output_conf[i].module_name);
505
506	ret = platform_driver_register(&mxr_driver);
507	if (ret != 0) {
508		pr_err("s5p-tv: registration of MIXER driver failed\n");
509		return -ENXIO;
510	}
511
512	return 0;
513}
514module_init(mxr_init);
515
516static void __exit mxr_exit(void)
517{
518	platform_driver_unregister(&mxr_driver);
519}
520module_exit(mxr_exit);
521