From 2c3fb08b3f74b8792004095a1f6881a3296ff643 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 14 Aug 2012 17:31:16 -0300 Subject: [media] rename drivers/media/video as .../platform The remaining drivers are mostly platform drivers. Name the dir to reflect it. It makes sense to latter break it into a few other dirs. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-tv/mixer_drv.c | 487 ++++++++++++++++++++++++++++++ 1 file changed, 487 insertions(+) create mode 100644 drivers/media/platform/s5p-tv/mixer_drv.c (limited to 'drivers/media/platform/s5p-tv/mixer_drv.c') diff --git a/drivers/media/platform/s5p-tv/mixer_drv.c b/drivers/media/platform/s5p-tv/mixer_drv.c new file mode 100644 index 00000000000..edca0659288 --- /dev/null +++ b/drivers/media/platform/s5p-tv/mixer_drv.c @@ -0,0 +1,487 @@ +/* + * Samsung TV Mixer driver + * + * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. + * + * Tomasz Stanislawski, + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundiation. either version 2 of the License, + * or (at your option) any later version + */ + +#include "mixer.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_AUTHOR("Tomasz Stanislawski, "); +MODULE_DESCRIPTION("Samsung MIXER"); +MODULE_LICENSE("GPL"); + +/* --------- DRIVER PARAMETERS ---------- */ + +static struct mxr_output_conf mxr_output_conf[] = { + { + .output_name = "S5P HDMI connector", + .module_name = "s5p-hdmi", + .cookie = 1, + }, + { + .output_name = "S5P SDO connector", + .module_name = "s5p-sdo", + .cookie = 0, + }, +}; + +void mxr_get_mbus_fmt(struct mxr_device *mdev, + struct v4l2_mbus_framefmt *mbus_fmt) +{ + struct v4l2_subdev *sd; + int ret; + + mutex_lock(&mdev->mutex); + sd = to_outsd(mdev); + ret = v4l2_subdev_call(sd, video, g_mbus_fmt, mbus_fmt); + WARN(ret, "failed to get mbus_fmt for output %s\n", sd->name); + mutex_unlock(&mdev->mutex); +} + +void mxr_streamer_get(struct mxr_device *mdev) +{ + mutex_lock(&mdev->mutex); + ++mdev->n_streamer; + mxr_dbg(mdev, "%s(%d)\n", __func__, mdev->n_streamer); + if (mdev->n_streamer == 1) { + struct v4l2_subdev *sd = to_outsd(mdev); + struct v4l2_mbus_framefmt mbus_fmt; + struct mxr_resources *res = &mdev->res; + int ret; + + if (to_output(mdev)->cookie == 0) + clk_set_parent(res->sclk_mixer, res->sclk_dac); + else + clk_set_parent(res->sclk_mixer, res->sclk_hdmi); + mxr_reg_s_output(mdev, to_output(mdev)->cookie); + + ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mbus_fmt); + WARN(ret, "failed to get mbus_fmt for output %s\n", sd->name); + ret = v4l2_subdev_call(sd, video, s_stream, 1); + WARN(ret, "starting stream failed for output %s\n", sd->name); + + mxr_reg_set_mbus_fmt(mdev, &mbus_fmt); + mxr_reg_streamon(mdev); + ret = mxr_reg_wait4vsync(mdev); + WARN(ret, "failed to get vsync (%d) from output\n", ret); + } + mutex_unlock(&mdev->mutex); + mxr_reg_dump(mdev); + /* FIXME: what to do when streaming fails? */ +} + +void mxr_streamer_put(struct mxr_device *mdev) +{ + mutex_lock(&mdev->mutex); + --mdev->n_streamer; + mxr_dbg(mdev, "%s(%d)\n", __func__, mdev->n_streamer); + if (mdev->n_streamer == 0) { + int ret; + struct v4l2_subdev *sd = to_outsd(mdev); + + mxr_reg_streamoff(mdev); + /* vsync applies Mixer setup */ + ret = mxr_reg_wait4vsync(mdev); + WARN(ret, "failed to get vsync (%d) from output\n", ret); + ret = v4l2_subdev_call(sd, video, s_stream, 0); + WARN(ret, "stopping stream failed for output %s\n", sd->name); + } + WARN(mdev->n_streamer < 0, "negative number of streamers (%d)\n", + mdev->n_streamer); + mutex_unlock(&mdev->mutex); + mxr_reg_dump(mdev); +} + +void mxr_output_get(struct mxr_device *mdev) +{ + mutex_lock(&mdev->mutex); + ++mdev->n_output; + mxr_dbg(mdev, "%s(%d)\n", __func__, mdev->n_output); + /* turn on auxiliary driver */ + if (mdev->n_output == 1) + v4l2_subdev_call(to_outsd(mdev), core, s_power, 1); + mutex_unlock(&mdev->mutex); +} + +void mxr_output_put(struct mxr_device *mdev) +{ + mutex_lock(&mdev->mutex); + --mdev->n_output; + mxr_dbg(mdev, "%s(%d)\n", __func__, mdev->n_output); + /* turn on auxiliary driver */ + if (mdev->n_output == 0) + v4l2_subdev_call(to_outsd(mdev), core, s_power, 0); + WARN(mdev->n_output < 0, "negative number of output users (%d)\n", + mdev->n_output); + mutex_unlock(&mdev->mutex); +} + +int mxr_power_get(struct mxr_device *mdev) +{ + int ret = pm_runtime_get_sync(mdev->dev); + + /* returning 1 means that power is already enabled, + * so zero success be returned */ + if (IS_ERR_VALUE(ret)) + return ret; + return 0; +} + +void mxr_power_put(struct mxr_device *mdev) +{ + pm_runtime_put_sync(mdev->dev); +} + +/* --------- RESOURCE MANAGEMENT -------------*/ + +static int __devinit mxr_acquire_plat_resources(struct mxr_device *mdev, + struct platform_device *pdev) +{ + struct resource *res; + int ret; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mxr"); + if (res == NULL) { + mxr_err(mdev, "get memory resource failed.\n"); + ret = -ENXIO; + goto fail; + } + + mdev->res.mxr_regs = ioremap(res->start, resource_size(res)); + if (mdev->res.mxr_regs == NULL) { + mxr_err(mdev, "register mapping failed.\n"); + ret = -ENXIO; + goto fail; + } + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vp"); + if (res == NULL) { + mxr_err(mdev, "get memory resource failed.\n"); + ret = -ENXIO; + goto fail_mxr_regs; + } + + mdev->res.vp_regs = ioremap(res->start, resource_size(res)); + if (mdev->res.vp_regs == NULL) { + mxr_err(mdev, "register mapping failed.\n"); + ret = -ENXIO; + goto fail_mxr_regs; + } + + res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq"); + if (res == NULL) { + mxr_err(mdev, "get interrupt resource failed.\n"); + ret = -ENXIO; + goto fail_vp_regs; + } + + ret = request_irq(res->start, mxr_irq_handler, 0, "s5p-mixer", mdev); + if (ret) { + mxr_err(mdev, "request interrupt failed.\n"); + goto fail_vp_regs; + } + mdev->res.irq = res->start; + + return 0; + +fail_vp_regs: + iounmap(mdev->res.vp_regs); + +fail_mxr_regs: + iounmap(mdev->res.mxr_regs); + +fail: + return ret; +} + +static void mxr_release_plat_resources(struct mxr_device *mdev) +{ + free_irq(mdev->res.irq, mdev); + iounmap(mdev->res.vp_regs); + iounmap(mdev->res.mxr_regs); +} + +static void mxr_release_clocks(struct mxr_device *mdev) +{ + struct mxr_resources *res = &mdev->res; + + if (!IS_ERR_OR_NULL(res->sclk_dac)) + clk_put(res->sclk_dac); + if (!IS_ERR_OR_NULL(res->sclk_hdmi)) + clk_put(res->sclk_hdmi); + if (!IS_ERR_OR_NULL(res->sclk_mixer)) + clk_put(res->sclk_mixer); + if (!IS_ERR_OR_NULL(res->vp)) + clk_put(res->vp); + if (!IS_ERR_OR_NULL(res->mixer)) + clk_put(res->mixer); +} + +static int mxr_acquire_clocks(struct mxr_device *mdev) +{ + struct mxr_resources *res = &mdev->res; + struct device *dev = mdev->dev; + + res->mixer = clk_get(dev, "mixer"); + if (IS_ERR_OR_NULL(res->mixer)) { + mxr_err(mdev, "failed to get clock 'mixer'\n"); + goto fail; + } + res->vp = clk_get(dev, "vp"); + if (IS_ERR_OR_NULL(res->vp)) { + mxr_err(mdev, "failed to get clock 'vp'\n"); + goto fail; + } + res->sclk_mixer = clk_get(dev, "sclk_mixer"); + if (IS_ERR_OR_NULL(res->sclk_mixer)) { + mxr_err(mdev, "failed to get clock 'sclk_mixer'\n"); + goto fail; + } + res->sclk_hdmi = clk_get(dev, "sclk_hdmi"); + if (IS_ERR_OR_NULL(res->sclk_hdmi)) { + mxr_err(mdev, "failed to get clock 'sclk_hdmi'\n"); + goto fail; + } + res->sclk_dac = clk_get(dev, "sclk_dac"); + if (IS_ERR_OR_NULL(res->sclk_dac)) { + mxr_err(mdev, "failed to get clock 'sclk_dac'\n"); + goto fail; + } + + return 0; +fail: + mxr_release_clocks(mdev); + return -ENODEV; +} + +static int __devinit mxr_acquire_resources(struct mxr_device *mdev, + struct platform_device *pdev) +{ + int ret; + ret = mxr_acquire_plat_resources(mdev, pdev); + + if (ret) + goto fail; + + ret = mxr_acquire_clocks(mdev); + if (ret) + goto fail_plat; + + mxr_info(mdev, "resources acquired\n"); + return 0; + +fail_plat: + mxr_release_plat_resources(mdev); +fail: + mxr_err(mdev, "resources acquire failed\n"); + return ret; +} + +static void mxr_release_resources(struct mxr_device *mdev) +{ + mxr_release_clocks(mdev); + mxr_release_plat_resources(mdev); + memset(&mdev->res, 0, sizeof mdev->res); +} + +static void mxr_release_layers(struct mxr_device *mdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(mdev->layer); ++i) + if (mdev->layer[i]) + mxr_layer_release(mdev->layer[i]); +} + +static int __devinit mxr_acquire_layers(struct mxr_device *mdev, + struct mxr_platform_data *pdata) +{ + mdev->layer[0] = mxr_graph_layer_create(mdev, 0); + mdev->layer[1] = mxr_graph_layer_create(mdev, 1); + mdev->layer[2] = mxr_vp_layer_create(mdev, 0); + + if (!mdev->layer[0] || !mdev->layer[1] || !mdev->layer[2]) { + mxr_err(mdev, "failed to acquire layers\n"); + goto fail; + } + + return 0; + +fail: + mxr_release_layers(mdev); + return -ENODEV; +} + +/* ---------- POWER MANAGEMENT ----------- */ + +static int mxr_runtime_resume(struct device *dev) +{ + struct mxr_device *mdev = to_mdev(dev); + struct mxr_resources *res = &mdev->res; + + mxr_dbg(mdev, "resume - start\n"); + mutex_lock(&mdev->mutex); + /* turn clocks on */ + clk_enable(res->mixer); + clk_enable(res->vp); + clk_enable(res->sclk_mixer); + /* apply default configuration */ + mxr_reg_reset(mdev); + mxr_dbg(mdev, "resume - finished\n"); + + mutex_unlock(&mdev->mutex); + return 0; +} + +static int mxr_runtime_suspend(struct device *dev) +{ + struct mxr_device *mdev = to_mdev(dev); + struct mxr_resources *res = &mdev->res; + mxr_dbg(mdev, "suspend - start\n"); + mutex_lock(&mdev->mutex); + /* turn clocks off */ + clk_disable(res->sclk_mixer); + clk_disable(res->vp); + clk_disable(res->mixer); + mutex_unlock(&mdev->mutex); + mxr_dbg(mdev, "suspend - finished\n"); + return 0; +} + +static const struct dev_pm_ops mxr_pm_ops = { + .runtime_suspend = mxr_runtime_suspend, + .runtime_resume = mxr_runtime_resume, +}; + +/* --------- DRIVER INITIALIZATION ---------- */ + +static int __devinit mxr_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct mxr_platform_data *pdata = dev->platform_data; + struct mxr_device *mdev; + int ret; + + /* mdev does not exist yet so no mxr_dbg is used */ + dev_info(dev, "probe start\n"); + + mdev = kzalloc(sizeof *mdev, GFP_KERNEL); + if (!mdev) { + mxr_err(mdev, "not enough memory.\n"); + ret = -ENOMEM; + goto fail; + } + + /* setup pointer to master device */ + mdev->dev = dev; + + mutex_init(&mdev->mutex); + spin_lock_init(&mdev->reg_slock); + init_waitqueue_head(&mdev->event_queue); + + /* acquire resources: regs, irqs, clocks, regulators */ + ret = mxr_acquire_resources(mdev, pdev); + if (ret) + goto fail_mem; + + /* configure resources for video output */ + ret = mxr_acquire_video(mdev, mxr_output_conf, + ARRAY_SIZE(mxr_output_conf)); + if (ret) + goto fail_resources; + + /* configure layers */ + ret = mxr_acquire_layers(mdev, pdata); + if (ret) + goto fail_video; + + pm_runtime_enable(dev); + + mxr_info(mdev, "probe successful\n"); + return 0; + +fail_video: + mxr_release_video(mdev); + +fail_resources: + mxr_release_resources(mdev); + +fail_mem: + kfree(mdev); + +fail: + dev_info(dev, "probe failed\n"); + return ret; +} + +static int __devexit mxr_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct mxr_device *mdev = to_mdev(dev); + + pm_runtime_disable(dev); + + mxr_release_layers(mdev); + mxr_release_video(mdev); + mxr_release_resources(mdev); + + kfree(mdev); + + dev_info(dev, "remove successful\n"); + return 0; +} + +static struct platform_driver mxr_driver __refdata = { + .probe = mxr_probe, + .remove = __devexit_p(mxr_remove), + .driver = { + .name = MXR_DRIVER_NAME, + .owner = THIS_MODULE, + .pm = &mxr_pm_ops, + } +}; + +static int __init mxr_init(void) +{ + int i, ret; + static const char banner[] __initconst = KERN_INFO + "Samsung TV Mixer driver, " + "(c) 2010-2011 Samsung Electronics Co., Ltd.\n"; + printk(banner); + + /* Loading auxiliary modules */ + for (i = 0; i < ARRAY_SIZE(mxr_output_conf); ++i) + request_module(mxr_output_conf[i].module_name); + + ret = platform_driver_register(&mxr_driver); + if (ret != 0) { + printk(KERN_ERR "registration of MIXER driver failed\n"); + return -ENXIO; + } + + return 0; +} +module_init(mxr_init); + +static void __exit mxr_exit(void) +{ + platform_driver_unregister(&mxr_driver); +} +module_exit(mxr_exit); -- cgit v1.2.3-70-g09d2 From f5c99037428b95da2ccc16daae6764b519ae0a90 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 11 Jun 2012 06:13:52 -0300 Subject: [media] s5p-tv: Replace printk with pr_* functions Replace printk with pr_* functions to silence checkpatch warnings. Signed-off-by: Sachin Kamat Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-tv/hdmi_drv.c | 6 ++++-- drivers/media/platform/s5p-tv/mixer_drv.c | 6 +++--- drivers/media/platform/s5p-tv/mixer_video.c | 4 +++- 3 files changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers/media/platform/s5p-tv/mixer_drv.c') diff --git a/drivers/media/platform/s5p-tv/hdmi_drv.c b/drivers/media/platform/s5p-tv/hdmi_drv.c index 20cb6eef297..8a9cf43018f 100644 --- a/drivers/media/platform/s5p-tv/hdmi_drv.c +++ b/drivers/media/platform/s5p-tv/hdmi_drv.c @@ -11,6 +11,8 @@ * or (at your option) any later version */ +#define pr_fmt(fmt) "s5p-tv (hdmi_drv): " fmt + #ifdef CONFIG_VIDEO_SAMSUNG_S5P_HDMI_DEBUG #define DEBUG #endif @@ -161,12 +163,12 @@ static irqreturn_t hdmi_irq_handler(int irq, void *dev_data) intc_flag = hdmi_read(hdev, HDMI_INTC_FLAG); /* clearing flags for HPD plug/unplug */ if (intc_flag & HDMI_INTC_FLAG_HPD_UNPLUG) { - printk(KERN_INFO "unplugged\n"); + pr_info("unplugged\n"); hdmi_write_mask(hdev, HDMI_INTC_FLAG, ~0, HDMI_INTC_FLAG_HPD_UNPLUG); } if (intc_flag & HDMI_INTC_FLAG_HPD_PLUG) { - printk(KERN_INFO "plugged\n"); + pr_info("plugged\n"); hdmi_write_mask(hdev, HDMI_INTC_FLAG, ~0, HDMI_INTC_FLAG_HPD_PLUG); } diff --git a/drivers/media/platform/s5p-tv/mixer_drv.c b/drivers/media/platform/s5p-tv/mixer_drv.c index edca0659288..a15ca0595b8 100644 --- a/drivers/media/platform/s5p-tv/mixer_drv.c +++ b/drivers/media/platform/s5p-tv/mixer_drv.c @@ -461,10 +461,10 @@ static struct platform_driver mxr_driver __refdata = { static int __init mxr_init(void) { int i, ret; - static const char banner[] __initconst = KERN_INFO + static const char banner[] __initconst = "Samsung TV Mixer driver, " "(c) 2010-2011 Samsung Electronics Co., Ltd.\n"; - printk(banner); + pr_info("%s\n", banner); /* Loading auxiliary modules */ for (i = 0; i < ARRAY_SIZE(mxr_output_conf); ++i) @@ -472,7 +472,7 @@ static int __init mxr_init(void) ret = platform_driver_register(&mxr_driver); if (ret != 0) { - printk(KERN_ERR "registration of MIXER driver failed\n"); + pr_err("s5p-tv: registration of MIXER driver failed\n"); return -ENXIO; } diff --git a/drivers/media/platform/s5p-tv/mixer_video.c b/drivers/media/platform/s5p-tv/mixer_video.c index e0e02cce1bc..a9c6be39246 100644 --- a/drivers/media/platform/s5p-tv/mixer_video.c +++ b/drivers/media/platform/s5p-tv/mixer_video.c @@ -11,6 +11,8 @@ * or (at your option) any later version */ +#define pr_fmt(fmt) "s5p-tv (mixer): " fmt + #include "mixer.h" #include @@ -1053,7 +1055,7 @@ void mxr_base_layer_release(struct mxr_layer *layer) static void mxr_vfd_release(struct video_device *vdev) { - printk(KERN_INFO "video device release\n"); + pr_info("video device release\n"); } struct mxr_layer *mxr_base_layer_create(struct mxr_device *mdev, -- cgit v1.2.3-70-g09d2 From 970e85f87067638262a5c165aff404e6190817f8 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Sat, 22 Sep 2012 03:39:19 -0300 Subject: [media] s5p-tv: Fix potential NULL pointer dereference error When mdev is NULL, the error print statement will try to dereference the NULL pointer. Signed-off-by: Sachin Kamat Acked-by: Tomasz Stanislawski Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-tv/mixer_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/platform/s5p-tv/mixer_drv.c') diff --git a/drivers/media/platform/s5p-tv/mixer_drv.c b/drivers/media/platform/s5p-tv/mixer_drv.c index a15ca0595b8..ca0f2971744 100644 --- a/drivers/media/platform/s5p-tv/mixer_drv.c +++ b/drivers/media/platform/s5p-tv/mixer_drv.c @@ -384,7 +384,7 @@ static int __devinit mxr_probe(struct platform_device *pdev) mdev = kzalloc(sizeof *mdev, GFP_KERNEL); if (!mdev) { - mxr_err(mdev, "not enough memory.\n"); + dev_err(dev, "not enough memory.\n"); ret = -ENOMEM; goto fail; } -- cgit v1.2.3-70-g09d2