Release 4.7 drivers/media/platform/s5p-tv/mixer_drv.c
/*
* Samsung TV Mixer driver
*
* Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
*
* Tomasz Stanislawski, <t.stanislaws@samsung.com>
*
* 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 <linux/module.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/fb.h>
#include <linux/delay.h>
#include <linux/pm_runtime.h>
#include <linux/clk.h>
MODULE_AUTHOR("Tomasz Stanislawski, <t.stanislaws@samsung.com>");
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;
struct v4l2_subdev_format fmt = {
.which = V4L2_SUBDEV_FORMAT_ACTIVE,
};
int ret;
mutex_lock(&mdev->mutex);
sd = to_outsd(mdev);
ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
*mbus_fmt = fmt.format;
WARN(ret, "failed to get mbus_fmt for output %s\n", sd->name);
mutex_unlock(&mdev->mutex);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
tomasz stanislawski | tomasz stanislawski | 67 | 73.63% | 1 | 50.00% |
hans verkuil | hans verkuil | 24 | 26.37% | 1 | 50.00% |
| Total | 91 | 100.00% | 2 | 100.00% |
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_subdev_format fmt = {
.which = V4L2_SUBDEV_FORMAT_ACTIVE,
};
struct v4l2_mbus_framefmt *mbus_fmt = &fmt.format;
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, pad, get_fmt, NULL, &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? */
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
tomasz stanislawski | tomasz stanislawski | 207 | 90.39% | 1 | 50.00% |
hans verkuil | hans verkuil | 22 | 9.61% | 1 | 50.00% |
| Total | 229 | 100.00% | 2 | 100.00% |
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);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
tomasz stanislawski | tomasz stanislawski | 133 | 100.00% | 1 | 100.00% |
| Total | 133 | 100.00% | 1 | 100.00% |
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);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
tomasz stanislawski | tomasz stanislawski | 67 | 100.00% | 1 | 100.00% |
| Total | 67 | 100.00% | 1 | 100.00% |
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);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
tomasz stanislawski | tomasz stanislawski | 82 | 100.00% | 1 | 100.00% |
| Total | 82 | 100.00% | 1 | 100.00% |
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 (ret < 0)
return ret;
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
tomasz stanislawski | tomasz stanislawski | 31 | 93.94% | 1 | 50.00% |
arnd bergmann | arnd bergmann | 2 | 6.06% | 1 | 50.00% |
| Total | 33 | 100.00% | 2 | 100.00% |
void mxr_power_put(struct mxr_device *mdev)
{
pm_runtime_put_sync(mdev->dev);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
tomasz stanislawski | tomasz stanislawski | 17 | 100.00% | 1 | 100.00% |
| Total | 17 | 100.00% | 1 | 100.00% |
/* --------- RESOURCE MANAGEMENT -------------*/
static int 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;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
tomasz stanislawski | tomasz stanislawski | 289 | 100.00% | 1 | 100.00% |
| Total | 289 | 100.00% | 1 | 100.00% |
static void mxr_resource_clear_clocks(struct mxr_resources *res)
{
res->mixer = ERR_PTR(-EINVAL);
res->vp = ERR_PTR(-EINVAL);
res->sclk_mixer = ERR_PTR(-EINVAL);
res->sclk_hdmi = ERR_PTR(-EINVAL);
res->sclk_dac = ERR_PTR(-EINVAL);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
sachin kamat | sachin kamat | 61 | 100.00% | 1 | 100.00% |
| Total | 61 | 100.00% | 1 | 100.00% |
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);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
tomasz stanislawski | tomasz stanislawski | 40 | 100.00% | 1 | 100.00% |
| Total | 40 | 100.00% | 1 | 100.00% |
static void mxr_release_clocks(struct mxr_device *mdev)
{
struct mxr_resources *res = &mdev->res;
if (!IS_ERR(res->sclk_dac))
clk_put(res->sclk_dac);
if (!IS_ERR(res->sclk_hdmi))
clk_put(res->sclk_hdmi);
if (!IS_ERR(res->sclk_mixer))
clk_put(res->sclk_mixer);
if (!IS_ERR(res->vp))
clk_put(res->vp);
if (!IS_ERR(res->mixer))
clk_put(res->mixer);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
tomasz stanislawski | tomasz stanislawski | 101 | 95.28% | 1 | 50.00% |
sachin kamat | sachin kamat | 5 | 4.72% | 1 | 50.00% |
| Total | 106 | 100.00% | 2 | 100.00% |
static int mxr_acquire_clocks(struct mxr_device *mdev)
{
struct mxr_resources *res = &mdev->res;
struct device *dev = mdev->dev;
mxr_resource_clear_clocks(res);
res->mixer = clk_get(dev, "mixer");
if (IS_ERR(res->mixer)) {
mxr_err(mdev, "failed to get clock 'mixer'\n");
goto fail;
}
res->vp = clk_get(dev, "vp");
if (IS_ERR(res->vp)) {
mxr_err(mdev, "failed to get clock 'vp'\n");
goto fail;
}
res->sclk_mixer = clk_get(dev, "sclk_mixer");
if (IS_ERR(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(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(res->sclk_dac)) {
mxr_err(mdev, "failed to get clock 'sclk_dac'\n");
goto fail;
}
return 0;
fail:
mxr_release_clocks(mdev);
return -ENODEV;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
tomasz stanislawski | tomasz stanislawski | 199 | 95.22% | 1 | 33.33% |
sachin kamat | sachin kamat | 5 | 2.39% | 1 | 33.33% |
tony prisk | tony prisk | 5 | 2.39% | 1 | 33.33% |
| Total | 209 | 100.00% | 3 | 100.00% |
static int 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;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
tomasz stanislawski | tomasz stanislawski | 78 | 100.00% | 1 | 100.00% |
| Total | 78 | 100.00% | 1 | 100.00% |
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));
mxr_resource_clear_clocks(&mdev->res);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
tomasz stanislawski | tomasz stanislawski | 36 | 78.26% | 1 | 33.33% |
sachin kamat | sachin kamat | 10 | 21.74% | 2 | 66.67% |
| Total | 46 | 100.00% | 3 | 100.00% |
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]);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
tomasz stanislawski | tomasz stanislawski | 51 | 100.00% | 1 | 100.00% |
| Total | 51 | 100.00% | 1 | 100.00% |
static int 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;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
tomasz stanislawski | tomasz stanislawski | 110 | 100.00% | 1 | 100.00% |
| Total | 110 | 100.00% | 1 | 100.00% |
/* ---------- POWER MANAGEMENT ----------- */
static int mxr_runtime_resume(struct device *dev)
{
struct mxr_device *mdev = to_mdev(dev);
struct mxr_resources *res = &mdev->res;
int ret;
mxr_dbg(mdev, "resume - start\n");
mutex_lock(&mdev->mutex);
/* turn clocks on */
ret = clk_prepare_enable(res->mixer);
if (ret < 0) {
dev_err(mdev->dev, "clk_prepare_enable(mixer) failed\n");
goto fail;
}
ret = clk_prepare_enable(res->vp);
if (ret < 0) {
dev_err(mdev->dev, "clk_prepare_enable(vp) failed\n");
goto fail_mixer;
}
ret = clk_prepare_enable(res->sclk_mixer);
if (ret < 0) {
dev_err(mdev->dev, "clk_prepare_enable(sclk_mixer) failed\n");
goto fail_vp;
}
/* apply default configuration */
mxr_reg_reset(mdev);
mxr_dbg(mdev, "resume - finished\n");
mutex_unlock(&mdev->mutex);
return 0;
fail_vp:
clk_disable_unprepare(res->vp);
fail_mixer:
clk_disable_unprepare(res->mixer);
fail:
mutex_unlock(&mdev->mutex);
dev_err(mdev->dev, "resume failed\n");
return ret;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
mateusz krawczuk | mateusz krawczuk | 112 | 55.72% | 1 | 50.00% |
tomasz stanislawski | tomasz stanislawski | 89 | 44.28% | 1 | 50.00% |
| Total | 201 | 100.00% | 2 | 100.00% |
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_unprepare(res->sclk_mixer);
clk_disable_unprepare(res->vp);
clk_disable_unprepare(res->mixer);
mutex_unlock(&mdev->mutex);
mxr_dbg(mdev, "suspend - finished\n");
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
tomasz stanislawski | tomasz stanislawski | 83 | 96.51% | 1 | 50.00% |
mateusz krawczuk | mateusz krawczuk | 3 | 3.49% | 1 | 50.00% |
| Total | 86 | 100.00% | 2 | 100.00% |
static const struct dev_pm_ops mxr_pm_ops = {
.runtime_suspend = mxr_runtime_suspend,
.runtime_resume = mxr_runtime_resume,
};
/* --------- DRIVER INITIALIZATION ---------- */
static int 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) {
dev_err(dev, "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;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
tomasz stanislawski | tomasz stanislawski | 211 | 97.69% | 1 | 33.33% |
sachin kamat | sachin kamat | 5 | 2.31% | 2 | 66.67% |
| Total | 216 | 100.00% | 3 | 100.00% |
static int 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;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
tomasz stanislawski | tomasz stanislawski | 65 | 98.48% | 1 | 50.00% |
masanari iida | masanari iida | 1 | 1.52% | 1 | 50.00% |
| Total | 66 | 100.00% | 2 | 100.00% |
static struct platform_driver mxr_driver __refdata = {
.probe = mxr_probe,
.remove = mxr_remove,
.driver = {
.name = MXR_DRIVER_NAME,
.pm = &mxr_pm_ops,
}
};
static int __init mxr_init(void)
{
int i, ret;
static const char banner[] __initconst =
"Samsung TV Mixer driver, "
"(c) 2010-2011 Samsung Electronics Co., Ltd.\n";
pr_info("%s\n", 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) {
pr_err("s5p-tv: registration of MIXER driver failed\n");
return -ENXIO;
}
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
tomasz stanislawski | tomasz stanislawski | 80 | 93.02% | 1 | 33.33% |
sachin kamat | sachin kamat | 5 | 5.81% | 1 | 33.33% |
uwe kleine-koenig | uwe kleine-koenig | 1 | 1.16% | 1 | 33.33% |
| Total | 86 | 100.00% | 3 | 100.00% |
module_init(mxr_init);
static void __exit mxr_exit(void)
{
platform_driver_unregister(&mxr_driver);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
tomasz stanislawski | tomasz stanislawski | 15 | 100.00% | 1 | 100.00% |
| Total | 15 | 100.00% | 1 | 100.00% |
module_exit(mxr_exit);
Overall Contributors
| Person | Tokens | Prop | Commits | CommitProp |
tomasz stanislawski | tomasz stanislawski | 2205 | 89.42% | 1 | 9.09% |
mateusz krawczuk | mateusz krawczuk | 115 | 4.66% | 1 | 9.09% |
sachin kamat | sachin kamat | 91 | 3.69% | 4 | 36.36% |
hans verkuil | hans verkuil | 46 | 1.87% | 1 | 9.09% |
tony prisk | tony prisk | 5 | 0.20% | 1 | 9.09% |
arnd bergmann | arnd bergmann | 2 | 0.08% | 1 | 9.09% |
uwe kleine-koenig | uwe kleine-koenig | 1 | 0.04% | 1 | 9.09% |
masanari iida | masanari iida | 1 | 0.04% | 1 | 9.09% |
| Total | 2466 | 100.00% | 11 | 100.00% |
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.