Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mixer_drv.c
Go to the documentation of this file.
1 /*
2  * Samsung TV Mixer driver
3  *
4  * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
5  *
6  * Tomasz Stanislawski, <[email protected]>
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, <[email protected]>");
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)
71  else
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  dev_err(dev, "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);
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 successful\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[] __initconst =
465  "Samsung TV Mixer driver, "
466  "(c) 2010-2011 Samsung Electronics Co., Ltd.\n";
467  pr_info("%s\n", 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  pr_err("s5p-tv: 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);