summaryrefslogtreecommitdiff
path: root/drivers/media/i2c/tvtuner.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/i2c/tvtuner.c')
-rw-r--r--drivers/media/i2c/tvtuner.c333
1 files changed, 333 insertions, 0 deletions
diff --git a/drivers/media/i2c/tvtuner.c b/drivers/media/i2c/tvtuner.c
new file mode 100644
index 000000000000..357491209814
--- /dev/null
+++ b/drivers/media/i2c/tvtuner.c
@@ -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");