I forgot but i have changed “camera_common.c”
I have added UYVY color format. So now i think YUV is missing in camera_common. Right? I need to modify for some other files for UYVY?
static const struct camera_common_colorfmt camera_common_color_fmts[] = {
{
V4L2_MBUS_FMT_SRGGB12_1X12,
V4L2_COLORSPACE_SRGB,
V4L2_PIX_FMT_SRGGB12,
},
{
V4L2_MBUS_FMT_SRGGB10_1X10,
V4L2_COLORSPACE_SRGB,
V4L2_PIX_FMT_SRGGB10,
},
{
V4L2_MBUS_FMT_SRGGB8_1X8,
V4L2_COLORSPACE_SRGB,
V4L2_PIX_FMT_SRGGB8,
},
{
V4L2_MBUS_FMT_UYVY8_2X8,
V4L2_COLORSPACE_SRGB,
V4L2_PIX_FMT_UYVY,
},
};
Below is my driver i have deleted some TC358748 I2C related functions.
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/seq_file.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <media/camera_common.h>
#include "cam_dev/camera_gpio.h"
enum {
TC358748_MODE_1920X1080,
};
static const int tc358748_60fps[] = {
60,
};
static const struct camera_common_frmfmt tc358748_frmfmt[] = {
{{1920, 1080}, tc358748_60fps, 1, 0, TC358748_MODE_1920X1080},
};
#define TC358748_DEFAULT_DATAFMT V4L2_MBUS_FMT_UYVY8_2X8
struct tc358748 {
struct camera_common_power_rail power;
int numctrls;
struct v4l2_ctrl_handler ctrl_handler;
struct i2c_client *i2c_client;
struct v4l2_subdev *subdev;
struct media_pad pad;
int reg_offset;
s32 group_hold_prev;
bool group_hold_en;
struct regmap *regmap;
struct camera_common_data *s_data;
struct camera_common_pdata *pdata;
struct v4l2_ctrl *ctrls[];
};
static int tc358748_power_on(struct camera_common_data *s_data)
{
int err = 0;
struct tc358748 *priv = (struct tc358748 *)s_data->priv;
struct camera_common_power_rail *pw = &priv->power;
dev_dbg(&priv->i2c_client->dev, "%s: power on\n", __func__);
if (priv->pdata && priv->pdata->power_on) {
err = priv->pdata->power_on(pw);
if (err)
pr_err("%s failed.\n", __func__);
else
pw->state = SWITCH_ON;
return err;
}
pw->state = SWITCH_ON;
return 0;
}
static int tc358748_power_off(struct camera_common_data *s_data)
{
int err = 0;
struct tc358748 *priv = (struct tc358748 *)s_data->priv;
struct camera_common_power_rail *pw = &priv->power;
dev_dbg(&priv->i2c_client->dev, "%s: power off\n", __func__);
if (priv->pdata && priv->pdata->power_on) {
err = priv->pdata->power_off(pw);
if (!err)
pw->state = SWITCH_OFF;
else
pr_err("%s failed.\n", __func__);
return err;
}
return 0;
}
static int tc358748_power_put(struct tc358748 *priv)
{
return 0;
}
static int tc358748_power_get(struct tc358748 *priv)
{
return 0;
}
static int tc358748_s_stream(struct v4l2_subdev *sd, int enable)
{
return 0;
}
static int tc358748_g_input_status(struct v4l2_subdev *sd, u32 *status)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct camera_common_data *s_data = to_camera_common_data(client);
struct tc358748 *priv = (struct tc358748 *)s_data->priv;
struct camera_common_power_rail *pw = &priv->power;
*status = pw->state == SWITCH_ON;
return 0;
}
static struct v4l2_subdev_video_ops tc358748_subdev_video_ops = {
.s_stream = tc358748_s_stream,
.s_mbus_fmt = camera_common_s_fmt,
.g_mbus_fmt = camera_common_g_fmt,
.try_mbus_fmt = camera_common_try_fmt,
.enum_mbus_fmt = camera_common_enum_fmt,
.g_mbus_config = camera_common_g_mbus_config,
.g_input_status = tc358748_g_input_status,
.enum_framesizes = camera_common_enum_framesizes,
.enum_frameintervals = camera_common_enum_frameintervals,
};
static struct v4l2_subdev_core_ops tc358748_subdev_core_ops = {
.s_power = camera_common_s_power,
};
static int tc358748_get_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_fh *fh,
struct v4l2_subdev_format *format)
{
return camera_common_g_fmt(sd, &format->format);
}
static int tc358748_set_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_fh *fh,
struct v4l2_subdev_format *format)
{
int ret;
if (format->which == V4L2_SUBDEV_FORMAT_TRY)
ret = camera_common_try_fmt(sd, &format->format);
else
ret = camera_common_s_fmt(sd, &format->format);
return ret;
}
static struct v4l2_subdev_pad_ops tc358748_subdev_pad_ops = {
.enum_mbus_code = camera_common_enum_mbus_code,
.set_fmt = tc358748_set_fmt,
.get_fmt = tc358748_get_fmt,
};
static struct v4l2_subdev_ops tc358748_subdev_ops = {
.core = &tc358748_subdev_core_ops,
.video = &tc358748_subdev_video_ops,
.pad = &tc358748_subdev_pad_ops,
};
static struct of_device_id tc358748_of_match[] = {
{ .compatible = "nvidia,tc358748", },
{ },
};
static struct camera_common_sensor_ops tc358748_common_ops = {
.power_on = tc358748_power_on,
.power_off = tc358748_power_off,
};
MODULE_DEVICE_TABLE(of, tc358748_of_match);
static struct camera_common_pdata *tc358748_parse_dt(struct i2c_client *client)
{
struct device_node *node = client->dev.of_node;
struct camera_common_pdata *board_priv_pdata;
const struct of_device_id *match;
int err;
if (!node)
return NULL;
match = of_match_device(tc358748_of_match, &client->dev);
if (!match) {
dev_err(&client->dev, "Failed to find matching dt id\n");
return NULL;
}
board_priv_pdata = devm_kzalloc(&client->dev,
sizeof(*board_priv_pdata), GFP_KERNEL);
if (!board_priv_pdata)
return NULL;
err = camera_common_parse_clocks(client, board_priv_pdata);
if (err) {
dev_err(&client->dev, "Failed to find clocks\n");
goto error;
}
return board_priv_pdata;
error:
devm_kfree(&client->dev, board_priv_pdata);
return NULL;
}
static int tc358748_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
dev_dbg(&client->dev, "%s:\n", __func__);
return 0;
}
static const struct v4l2_subdev_internal_ops tc358748_subdev_internal_ops = {
.open = tc358748_open,
};
static const struct media_entity_operations tc358748_media_ops = {
.link_validate = v4l2_subdev_link_validate,
};
static int tc358748_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct camera_common_data *common_data;
struct device_node *node = client->dev.of_node;
struct tc358748 *priv;
char debugfs_name[10];
int err;
int ReadData, i;
pr_info("[TC358748]: [Ritesh] probing v4l2 sensor.\n");
if (!IS_ENABLED(CONFIG_OF) || !node)
{
pr_info("[TC358748]: [Ritesh] IS_ENABLED(CONFIG_OF).\n");
return -EINVAL;
}
common_data = devm_kzalloc(&client->dev,
sizeof(struct camera_common_data), GFP_KERNEL);
if (!common_data)
{
pr_info("[TC358748]: [Ritesh] common_data.\n");
return -ENOMEM;
}
priv = devm_kzalloc(&client->dev,sizeof(struct tc358748),GFP_KERNEL);
priv->pdata = tc358748_parse_dt(client);
if (!priv->pdata) {
dev_err(&client->dev, "unable to get platform data\n");
pr_info("[TC358748]: [Ritesh]unable to get platform data\n");
return -EFAULT;
}
common_data->ops = &tc358748_common_ops;
common_data->i2c_client = client;
common_data->frmfmt = tc358748_frmfmt;
common_data->colorfmt = camera_common_find_datafmt(TC358748_DEFAULT_DATAFMT);
common_data->power = &priv->power;
common_data->priv = (void *)priv;
common_data->numfmts = ARRAY_SIZE(tc358748_frmfmt);
common_data->def_mode = TC358748_MODE_1920X1080;
common_data->def_width = 1920;
common_data->def_height = 1080;
common_data->fmt_width = common_data->def_width;
common_data->fmt_height = common_data->def_height;
common_data->def_clk_freq = 24000000;
priv->i2c_client = client;
priv->s_data = common_data;
priv->subdev = &common_data->subdev;
priv->subdev->dev = &client->dev;
priv->s_data->dev = &client->dev;
err = tc358748_power_get(priv);
if (err)
return err;
err = camera_common_parse_ports(client, common_data);
if (err) {
dev_err(&client->dev, "Failed to find port info\n");
pr_info("[TC358748]: [Ritesh] Failed to find port info.\n");
return err;
}
sprintf(debugfs_name, "tc358748_%c", common_data->csi_port + 'a');
dev_dbg(&client->dev, "%s: name %s\n", __func__, debugfs_name);
camera_common_create_debugfs(common_data, debugfs_name);
v4l2_i2c_subdev_init(priv->subdev, client, &tc358748_subdev_ops);
priv->subdev->internal_ops = &tc358748_subdev_internal_ops;
priv->subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
V4L2_SUBDEV_FL_HAS_EVENTS;
#if defined(CONFIG_MEDIA_CONTROLLER)
priv->pad.flags = MEDIA_PAD_FL_SOURCE;
priv->subdev->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
priv->subdev->entity.ops = &tc358748_media_ops;
err = media_entity_init(&priv->subdev->entity, 1, &priv->pad, 0);
pr_info("[TC358748]: [Ritesh] Media Controller.\n");
if (err < 0) {
dev_err(&client->dev, "unable to init media entity\n");
pr_info("[TC358748]: [Ritesh] unable to init media entity.\n");
return err;
}
#endif
err = v4l2_async_register_subdev(priv->subdev);
if (err)
{
pr_info("[TC358748]: [Ritesh] v4l2_async_register_subdev.\n");
return err;
}
tc358748_write_table(client,
tc358748_setting_YUV422_4lane_1080P_60fps_1920_1080,
ARRAY_SIZE(tc358748_setting_YUV422_4lane_1080P_60fps_1920_1080));
for(i = 0; i < 27; i++)
{
ReadData = i2c_rd(client, tc358748_setting_YUV422_4lane_1080P_60fps_1920_1080[i].addr, tc358748_setting_YUV422_4lane_1080P_60fps_1920_1080[i].len);
pr_err("[TC] ADDR: 0x%04x, Write: 0x%08x, Read: 0x%08x \n", tc358748_setting_YUV422_4lane_1080P_60fps_1920_1080[i].addr, tc358748_setting_YUV422_4lane_1080P_60fps_1920_1080[i].val, ReadData);
}
dev_dbg(&client->dev, "Detected TC358748 sensor\n");
return 0;
}
static int
tc358748_remove(struct i2c_client *client)
{
struct camera_common_data *s_data = to_camera_common_data(client);
struct tc358748 *priv = (struct tc358748 *)s_data->priv;
v4l2_async_unregister_subdev(priv->subdev);
#if defined(CONFIG_MEDIA_CONTROLLER)
media_entity_cleanup(&priv->subdev->entity);
#endif
v4l2_ctrl_handler_free(&priv->ctrl_handler);
tc358748_power_put(priv);
camera_common_remove_debugfs(s_data);
return 0;
}
static const struct i2c_device_id tc358748_id[] = {
{ "tc358748", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, tc358748_id);
static struct i2c_driver tc358748_i2c_driver = {
.driver = {
.name = "tc358748",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(tc358748_of_match),
},
.probe = tc358748_probe,
.remove = tc358748_remove,
.id_table = tc358748_id,
};
module_i2c_driver(tc358748_i2c_driver);
MODULE_DESCRIPTION("Camera driver for Toshiba TC358748");
MODULE_AUTHOR("Ritesh Panchal <ritesh@syntronstech.com>");
MODULE_LICENSE("GPL v2");
As i am testing the driver i have only added support for single fixed format without any ioctl or v4l2_ctrl_handler.