TvTuner: Add support for TV tuner driver
Add new dummy tv tuner driver and its documentation. Update Makefile, Kconfig and add new tuner id type to msm_ba.h Change-Id: I14f822ad9fdf85ea7509067d536c49fd24cf1609 Signed-off-by: Rahul Sharma <sharah@codeaurora.org>
This commit is contained in:
parent
720aa591f4
commit
ff2dc69c5a
9 changed files with 387 additions and 3 deletions
15
Documentation/devicetree/bindings/arm/msm/tv-tuner.txt
Normal file
15
Documentation/devicetree/bindings/arm/msm/tv-tuner.txt
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
TVTUNER driver (VIDEO_TVTUNER)
|
||||||
|
|
||||||
|
VIDEO_TVTUNER is a sample kernel platform driver that is used to control the tv
|
||||||
|
tuner hardware for the capture of Tv tuner received a/v signal.
|
||||||
|
|
||||||
|
The devicetree representation of the VIDEO_TVTUNER block should be:
|
||||||
|
|
||||||
|
Required properties
|
||||||
|
|
||||||
|
- compatible: "qcom,tv-tuner"
|
||||||
|
|
||||||
|
Example:
|
||||||
|
qcom,tv-tuner {
|
||||||
|
compatible = "qcom,tv-tuner";
|
||||||
|
};
|
|
@ -12,7 +12,7 @@ Required properties:
|
||||||
"qcom,name", "qcom,ba-input", "qcom,ba-output", "qcom,sd-name",
|
"qcom,name", "qcom,ba-input", "qcom,ba-output", "qcom,sd-name",
|
||||||
"qcom,ba-node" and "qcom,user-type".
|
"qcom,ba-node" and "qcom,user-type".
|
||||||
Required properties:
|
Required properties:
|
||||||
- qcom,type: Input type such as CVBS(0), HDMI(4) etc as defined in BA driver.
|
- qcom,type: Input type such as CVBS(0), HDMI(4), TUNER(8) etc as defined in BA driver.
|
||||||
This property is of type u32.
|
This property is of type u32.
|
||||||
- qcom,name: Name of the input type. This property is of type string.
|
- qcom,name: Name of the input type. This property is of type string.
|
||||||
- qcom,ba-input: BA input id supported by a bridge chip for this profile.
|
- qcom,ba-input: BA input id supported by a bridge chip for this profile.
|
||||||
|
|
|
@ -233,6 +233,18 @@ config VIDEO_ADV7481
|
||||||
To compile this driver as a module, choose M here: the
|
To compile this driver as a module, choose M here: the
|
||||||
module will be called adv7481.
|
module will be called adv7481.
|
||||||
|
|
||||||
|
config VIDEO_TVTUNER
|
||||||
|
tristate "Analog Tv Tuner driver"
|
||||||
|
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
|
||||||
|
---help---
|
||||||
|
Support for the Dummy TV Tuner.
|
||||||
|
|
||||||
|
This is a Dummy TV Tuner Driver to Validate call flow
|
||||||
|
from tv_input_test unit-test app.
|
||||||
|
|
||||||
|
To compile this driver as a module, choose M here: the
|
||||||
|
module will be called tv-tuner.
|
||||||
|
|
||||||
config VIDEO_BT819
|
config VIDEO_BT819
|
||||||
tristate "BT819A VideoStream decoder"
|
tristate "BT819A VideoStream decoder"
|
||||||
depends on VIDEO_V4L2 && I2C
|
depends on VIDEO_V4L2 && I2C
|
||||||
|
|
|
@ -39,6 +39,7 @@ ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/io
|
||||||
ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/cci
|
ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/cci
|
||||||
endif
|
endif
|
||||||
obj-$(CONFIG_VIDEO_ADV7481) += adv7481.o
|
obj-$(CONFIG_VIDEO_ADV7481) += adv7481.o
|
||||||
|
obj-$(CONFIG_VIDEO_TVTUNER) += tvtuner.o
|
||||||
obj-$(CONFIG_VIDEO_AD9389B) += ad9389b.o
|
obj-$(CONFIG_VIDEO_AD9389B) += ad9389b.o
|
||||||
obj-$(CONFIG_VIDEO_ADV7511) += adv7511.o
|
obj-$(CONFIG_VIDEO_ADV7511) += adv7511.o
|
||||||
obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o
|
obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o
|
||||||
|
|
333
drivers/media/i2c/tvtuner.c
Normal file
333
drivers/media/i2c/tvtuner.c
Normal file
|
@ -0,0 +1,333 @@
|
||||||
|
/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
* only version 2 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/media.h>
|
||||||
|
#include <media/v4l2-ioctl.h>
|
||||||
|
#include <linux/videodev2.h>
|
||||||
|
#include <media/v4l2-device.h>
|
||||||
|
#include <media/v4l2-ctrls.h>
|
||||||
|
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/of_platform.h>
|
||||||
|
|
||||||
|
#include <media/msm_ba.h>
|
||||||
|
|
||||||
|
#include "tvtuner.h"
|
||||||
|
|
||||||
|
#define DRIVER_NAME "tv-tuner"
|
||||||
|
|
||||||
|
struct Tvtuner_state {
|
||||||
|
struct device *dev;
|
||||||
|
|
||||||
|
/* V4L2 Data */
|
||||||
|
struct v4l2_subdev sd;
|
||||||
|
struct v4l2_ctrl_handler ctrl_hdl;
|
||||||
|
struct v4l2_dv_timings timings;
|
||||||
|
|
||||||
|
/* media entity controls */
|
||||||
|
struct media_pad pad;
|
||||||
|
|
||||||
|
struct mutex mutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Initialize Tvtuner I2C Settings */
|
||||||
|
static int Tvtuner_dev_init(struct Tvtuner_state *state)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
TUNER_DEBUG("tv_tuner dev init is started\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize Tvtuner hardware */
|
||||||
|
static int Tvtuner_hw_init(struct Tvtuner_state *state)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
TUNER_DEBUG("tv_tuner hw init is started\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int Tvtuner_s_ctrl(struct v4l2_ctrl *ctrl)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
TUNER_DEBUG("tv_tuner set control is started id = 0x%x\n", ctrl->id);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int Tvtuner_get_fmt(struct v4l2_subdev *sd,
|
||||||
|
struct v4l2_subdev_pad_config *cfg,
|
||||||
|
struct v4l2_subdev_format *format)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
struct v4l2_mbus_framefmt *fmt = &format->format;
|
||||||
|
|
||||||
|
fmt->code = MEDIA_BUS_FMT_UYVY8_2X8;
|
||||||
|
fmt->width = 1280;
|
||||||
|
fmt->height = 720;
|
||||||
|
fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
|
||||||
|
|
||||||
|
TUNER_DEBUG("tv_tuner get mbus format is started\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int Tvtuner_g_frame_interval(struct v4l2_subdev *sd,
|
||||||
|
struct v4l2_subdev_frame_interval *interval)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
TUNER_DEBUG("tv_tuner get frame interval is started\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int Tvtuner_s_routing(struct v4l2_subdev *sd, u32 input,
|
||||||
|
u32 output, u32 config)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
TUNER_DEBUG("tv_tuner s_routing is started\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int Tvtuner_query_dv_timings(struct v4l2_subdev *sd,
|
||||||
|
struct v4l2_dv_timings *timings)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
TUNER_DEBUG("tv_tuner query dv timings is started\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int Tvtuner_query_sd_std(struct v4l2_subdev *sd, v4l2_std_id *std)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
TUNER_DEBUG("tv_tuner query SD input is started\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int Tvtuner_g_input_status(struct v4l2_subdev *sd, u32 *status)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
*status = 1;
|
||||||
|
|
||||||
|
TUNER_DEBUG("tv_tuner get input status is started\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int Tvtuner_s_stream(struct v4l2_subdev *sd, int on)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
TUNER_DEBUG("tv_tuner start stream is started\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct v4l2_subdev_video_ops Tvtuner_video_ops = {
|
||||||
|
.s_routing = Tvtuner_s_routing,
|
||||||
|
.g_frame_interval = Tvtuner_g_frame_interval,
|
||||||
|
.querystd = Tvtuner_query_sd_std,
|
||||||
|
.g_dv_timings = Tvtuner_query_dv_timings,
|
||||||
|
.g_input_status = Tvtuner_g_input_status,
|
||||||
|
.s_stream = Tvtuner_s_stream,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static const struct v4l2_ctrl_ops Tvtuner_ctrl_ops = {
|
||||||
|
.s_ctrl = Tvtuner_s_ctrl,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct v4l2_subdev_pad_ops Tvtuner_pad_ops = {
|
||||||
|
.get_fmt = Tvtuner_get_fmt,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct v4l2_subdev_ops Tvtuner_ops = {
|
||||||
|
.video = &Tvtuner_video_ops,
|
||||||
|
.pad = &Tvtuner_pad_ops,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int Tvtuner_init_v4l2_controls(struct Tvtuner_state *state)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
TUNER_DEBUG("%s: Exit with ret: %d\n", __func__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int Tvtuner_parse_dt(struct platform_device *pdev,
|
||||||
|
struct Tvtuner_state *state)
|
||||||
|
{
|
||||||
|
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
TUNER_DEBUG("%s: tvtuner parse dt called\n", __func__);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct of_device_id Tvtuner_id[] = {
|
||||||
|
{ .compatible = "qcom,tv-tuner", },
|
||||||
|
{},
|
||||||
|
};
|
||||||
|
|
||||||
|
MODULE_DEVICE_TABLE(of, Tvtuner_id);
|
||||||
|
|
||||||
|
static int Tvtuner_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct Tvtuner_state *state;
|
||||||
|
const struct of_device_id *device_id;
|
||||||
|
struct v4l2_subdev *sd;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
device_id = of_match_device(Tvtuner_id, &pdev->dev);
|
||||||
|
if (!device_id) {
|
||||||
|
TUNER_DEBUG("%s: device_id is NULL\n", __func__);
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create Tvtuner State */
|
||||||
|
state = devm_kzalloc(&pdev->dev,
|
||||||
|
sizeof(struct Tvtuner_state), GFP_KERNEL);
|
||||||
|
if (state == NULL) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
platform_set_drvdata(pdev, state);
|
||||||
|
state->dev = &pdev->dev;
|
||||||
|
|
||||||
|
mutex_init(&state->mutex);
|
||||||
|
ret = Tvtuner_parse_dt(pdev, state);
|
||||||
|
if (ret < 0) {
|
||||||
|
TUNER_ERROR("Error parsing dt tree\n");
|
||||||
|
goto err_mem_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Configure and Register V4L2 Sub-device */
|
||||||
|
sd = &state->sd;
|
||||||
|
v4l2_subdev_init(sd, &Tvtuner_ops);
|
||||||
|
sd->owner = pdev->dev.driver->owner;
|
||||||
|
v4l2_set_subdevdata(sd, state);
|
||||||
|
strlcpy(sd->name, DRIVER_NAME, sizeof(sd->name));
|
||||||
|
state->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
|
||||||
|
state->sd.flags |= V4L2_SUBDEV_FL_HAS_EVENTS;
|
||||||
|
|
||||||
|
/* Register as Media Entity */
|
||||||
|
state->pad.flags = MEDIA_PAD_FL_SOURCE;
|
||||||
|
state->sd.entity.flags |= (unsigned long)MEDIA_ENT_T_V4L2_SUBDEV;
|
||||||
|
ret = media_entity_init(&state->sd.entity, 1, &state->pad, 0);
|
||||||
|
if (ret) {
|
||||||
|
ret = -EIO;
|
||||||
|
TUNER_ERROR("%s(%d): Media entity init failed\n",
|
||||||
|
__func__, __LINE__);
|
||||||
|
goto err_media_entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize HW Config */
|
||||||
|
ret = Tvtuner_hw_init(state);
|
||||||
|
if (ret) {
|
||||||
|
ret = -EIO;
|
||||||
|
TUNER_ERROR("%s: HW Initialisation Failed\n", __func__);
|
||||||
|
goto err_media_entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = Tvtuner_init_v4l2_controls(state);
|
||||||
|
if (ret) {
|
||||||
|
TUNER_ERROR("%s: V4L2 Controls Initialisation Failed %d\n",
|
||||||
|
__func__, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize SW Init Settings and I2C sub maps */
|
||||||
|
ret = Tvtuner_dev_init(state);
|
||||||
|
if (ret) {
|
||||||
|
ret = -EIO;
|
||||||
|
TUNER_ERROR("%s(%d): SW Initialisation Failed\n",
|
||||||
|
__func__, __LINE__);
|
||||||
|
goto err_media_entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* BA registration */
|
||||||
|
TUNER_DEBUG(" register msm-ba driver to tv_tuner");
|
||||||
|
ret = msm_ba_register_subdev_node(sd);
|
||||||
|
if (ret) {
|
||||||
|
ret = -EIO;
|
||||||
|
TUNER_DEBUG("%s: BA init failed\n", __func__);
|
||||||
|
goto err_media_entity;
|
||||||
|
}
|
||||||
|
TUNER_DEBUG("Probe of tvtuner successful!\n");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
err_media_entity:
|
||||||
|
media_entity_cleanup(&sd->entity);
|
||||||
|
|
||||||
|
err_mem_free:
|
||||||
|
devm_kfree(&pdev->dev, state);
|
||||||
|
|
||||||
|
err:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int Tvtuner_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct Tvtuner_state *state = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
|
msm_ba_unregister_subdev_node(&state->sd);
|
||||||
|
v4l2_device_unregister_subdev(&state->sd);
|
||||||
|
media_entity_cleanup(&state->sd.entity);
|
||||||
|
|
||||||
|
v4l2_ctrl_handler_free(&state->ctrl_hdl);
|
||||||
|
|
||||||
|
mutex_destroy(&state->mutex);
|
||||||
|
devm_kfree(&pdev->dev, state);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int Tvtuner_suspend(struct device *dev)
|
||||||
|
{
|
||||||
|
TUNER_DEBUG("tv_tuner driver is in suspend state\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int Tvtuner_resume(struct device *dev)
|
||||||
|
{
|
||||||
|
TUNER_DEBUG("tv_tuner driver is in resume state\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SIMPLE_DEV_PM_OPS(Tvtuner_pm_ops, Tvtuner_suspend, Tvtuner_resume);
|
||||||
|
#define TVTUNER_PM_OPS (&Tvtuner_pm_ops)
|
||||||
|
|
||||||
|
static struct platform_driver Tvtuner_driver = {
|
||||||
|
.driver = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.name = "tv-tuner",
|
||||||
|
.of_match_table = Tvtuner_id,
|
||||||
|
.pm = TVTUNER_PM_OPS,
|
||||||
|
},
|
||||||
|
.probe = Tvtuner_probe,
|
||||||
|
.remove = Tvtuner_remove,
|
||||||
|
};
|
||||||
|
|
||||||
|
module_driver(Tvtuner_driver, platform_driver_register,
|
||||||
|
platform_driver_unregister);
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION(" TV TUNER Test driver");
|
||||||
|
MODULE_LICENSE("GPL v2");
|
23
drivers/media/i2c/tvtuner.h
Normal file
23
drivers/media/i2c/tvtuner.h
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017, The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
* only version 2 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __TV_TUNER_H__
|
||||||
|
#define __TV_TUNER_H__
|
||||||
|
|
||||||
|
#define PREFIX "tv_tuner: "
|
||||||
|
|
||||||
|
#define TUNER_DEBUG(str, args...) pr_debug(PREFIX str, ##args)
|
||||||
|
#define TUNER_ERROR(str, args...) pr_err(PREFIX str, ##args)
|
||||||
|
|
||||||
|
#endif
|
|
@ -191,8 +191,6 @@ void msm_ba_add_inputs(struct v4l2_subdev *sd)
|
||||||
int dev_id = 0;
|
int dev_id = 0;
|
||||||
|
|
||||||
dev_ctxt = get_ba_dev();
|
dev_ctxt = get_ba_dev();
|
||||||
if (!list_empty(&dev_ctxt->inputs))
|
|
||||||
start_index = dev_ctxt->num_inputs;
|
|
||||||
|
|
||||||
msm_ba_inp_cfg = dev_ctxt->msm_ba_inp_cfg;
|
msm_ba_inp_cfg = dev_ctxt->msm_ba_inp_cfg;
|
||||||
dev_id = msm_ba_inp_cfg[start_index].ba_out;
|
dev_id = msm_ba_inp_cfg[start_index].ba_out;
|
||||||
|
|
|
@ -106,6 +106,7 @@ enum msm_ba_ip_type {
|
||||||
BA_INPUT_MHL,
|
BA_INPUT_MHL,
|
||||||
BA_INPUT_DVI,
|
BA_INPUT_DVI,
|
||||||
BA_INPUT_TTL,
|
BA_INPUT_TTL,
|
||||||
|
BA_INPUT_TV_TUNER,
|
||||||
BA_INPUT_MAX = 0xffffffff
|
BA_INPUT_MAX = 0xffffffff
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ enum msm_ba_ip {
|
||||||
BA_IP_HDMI_1,
|
BA_IP_HDMI_1,
|
||||||
BA_IP_MHL_1,
|
BA_IP_MHL_1,
|
||||||
BA_IP_TTL,
|
BA_IP_TTL,
|
||||||
|
BA_IP_TV_TUNER,
|
||||||
BA_IP_MAX = 0xffffffff
|
BA_IP_MAX = 0xffffffff
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue