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