1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Support for Medifield PNW Camera Imaging ISP subsystem.
4  *
5  * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
6  *
7  * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License version
11  * 2 as published by the Free Software Foundation.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  *
19  */
20 
21 #include <media/v4l2-event.h>
22 #include <media/v4l2-mediabus.h>
23 #include "atomisp_internal.h"
24 #include "atomisp_tpg.h"
25 
tpg_s_stream(struct v4l2_subdev * sd,int enable)26 static int tpg_s_stream(struct v4l2_subdev *sd, int enable)
27 {
28 	return 0;
29 }
30 
tpg_get_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_format * format)31 static int tpg_get_fmt(struct v4l2_subdev *sd,
32 		       struct v4l2_subdev_pad_config *cfg,
33 		       struct v4l2_subdev_format *format)
34 {
35 	/*to fake*/
36 	return 0;
37 }
38 
tpg_set_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_format * format)39 static int tpg_set_fmt(struct v4l2_subdev *sd,
40 		       struct v4l2_subdev_pad_config *cfg,
41 		       struct v4l2_subdev_format *format)
42 {
43 	struct v4l2_mbus_framefmt *fmt = &format->format;
44 
45 	if (format->pad)
46 		return -EINVAL;
47 	/* only raw8 grbg is supported by TPG */
48 	fmt->code = MEDIA_BUS_FMT_SGRBG8_1X8;
49 	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
50 		cfg->try_fmt = *fmt;
51 		return 0;
52 	}
53 	return 0;
54 }
55 
tpg_log_status(struct v4l2_subdev * sd)56 static int tpg_log_status(struct v4l2_subdev *sd)
57 {
58 	/*to fake*/
59 	return 0;
60 }
61 
tpg_s_power(struct v4l2_subdev * sd,int on)62 static int tpg_s_power(struct v4l2_subdev *sd, int on)
63 {
64 	return 0;
65 }
66 
tpg_enum_mbus_code(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_mbus_code_enum * code)67 static int tpg_enum_mbus_code(struct v4l2_subdev *sd,
68 			      struct v4l2_subdev_pad_config *cfg,
69 			      struct v4l2_subdev_mbus_code_enum *code)
70 {
71 	/*to fake*/
72 	return 0;
73 }
74 
tpg_enum_frame_size(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_frame_size_enum * fse)75 static int tpg_enum_frame_size(struct v4l2_subdev *sd,
76 			       struct v4l2_subdev_pad_config *cfg,
77 			       struct v4l2_subdev_frame_size_enum *fse)
78 {
79 	/*to fake*/
80 	return 0;
81 }
82 
tpg_enum_frame_ival(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_frame_interval_enum * fie)83 static int tpg_enum_frame_ival(struct v4l2_subdev *sd,
84 			       struct v4l2_subdev_pad_config *cfg,
85 			       struct v4l2_subdev_frame_interval_enum *fie)
86 {
87 	/*to fake*/
88 	return 0;
89 }
90 
91 static const struct v4l2_subdev_video_ops tpg_video_ops = {
92 	.s_stream = tpg_s_stream,
93 };
94 
95 static const struct v4l2_subdev_core_ops tpg_core_ops = {
96 	.log_status = tpg_log_status,
97 	.s_power = tpg_s_power,
98 };
99 
100 static const struct v4l2_subdev_pad_ops tpg_pad_ops = {
101 	.enum_mbus_code = tpg_enum_mbus_code,
102 	.enum_frame_size = tpg_enum_frame_size,
103 	.enum_frame_interval = tpg_enum_frame_ival,
104 	.get_fmt = tpg_get_fmt,
105 	.set_fmt = tpg_set_fmt,
106 };
107 
108 static const struct v4l2_subdev_ops tpg_ops = {
109 	.core = &tpg_core_ops,
110 	.video = &tpg_video_ops,
111 	.pad = &tpg_pad_ops,
112 };
113 
atomisp_tpg_unregister_entities(struct atomisp_tpg_device * tpg)114 void atomisp_tpg_unregister_entities(struct atomisp_tpg_device *tpg)
115 {
116 	media_entity_cleanup(&tpg->sd.entity);
117 	v4l2_device_unregister_subdev(&tpg->sd);
118 }
119 
atomisp_tpg_register_entities(struct atomisp_tpg_device * tpg,struct v4l2_device * vdev)120 int atomisp_tpg_register_entities(struct atomisp_tpg_device *tpg,
121 				  struct v4l2_device *vdev)
122 {
123 	int ret;
124 	/* Register the subdev and video nodes. */
125 	ret = v4l2_device_register_subdev(vdev, &tpg->sd);
126 	if (ret < 0)
127 		goto error;
128 
129 	return 0;
130 
131 error:
132 	atomisp_tpg_unregister_entities(tpg);
133 	return ret;
134 }
135 
atomisp_tpg_cleanup(struct atomisp_device * isp)136 void atomisp_tpg_cleanup(struct atomisp_device *isp)
137 {
138 }
139 
atomisp_tpg_init(struct atomisp_device * isp)140 int atomisp_tpg_init(struct atomisp_device *isp)
141 {
142 	struct atomisp_tpg_device *tpg = &isp->tpg;
143 	struct v4l2_subdev *sd = &tpg->sd;
144 	struct media_pad *pads = tpg->pads;
145 	struct media_entity *me = &sd->entity;
146 	int ret;
147 
148 	tpg->isp = isp;
149 	v4l2_subdev_init(sd, &tpg_ops);
150 	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
151 	strscpy(sd->name, "tpg_subdev", sizeof(sd->name));
152 	v4l2_set_subdevdata(sd, tpg);
153 
154 	pads[0].flags = MEDIA_PAD_FL_SINK;
155 	me->function = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN;
156 
157 	ret = media_entity_pads_init(me, 1, pads);
158 	if (ret < 0)
159 		goto fail;
160 	return 0;
161 fail:
162 	atomisp_tpg_cleanup(isp);
163 	return ret;
164 }
165