|
7 | 7 | #define DT_DRV_COMPAT nxp_mipi_csi2rx
|
8 | 8 |
|
9 | 9 | #include <zephyr/drivers/video.h>
|
| 10 | +#include <zephyr/drivers/video-controls.h> |
10 | 11 | #include <zephyr/kernel.h>
|
11 | 12 | #include <zephyr/logging/log.h>
|
12 | 13 | #include <soc.h>
|
@@ -173,13 +174,125 @@ static inline int mipi_csi2rx_set_ctrl(const struct device *dev, unsigned int ci
|
173 | 174 | return -ENOTSUP;
|
174 | 175 | }
|
175 | 176 |
|
| 177 | +static int mipi_csi2rx_set_frmival(const struct device *dev, enum video_endpoint_id ep, |
| 178 | + struct video_frmival *frmival) |
| 179 | +{ |
| 180 | + const struct mipi_csi2rx_config *config = dev->config; |
| 181 | + int ret; |
| 182 | + |
| 183 | + ret = video_set_frmival(config->sensor_dev, ep, frmival); |
| 184 | + if (ret) { |
| 185 | + LOG_ERR("Cannot set sensor_dev frmival"); |
| 186 | + return ret; |
| 187 | + } |
| 188 | + |
| 189 | + ret = mipi_csi2rx_update_settings(dev, ep); |
| 190 | + |
| 191 | + return ret; |
| 192 | +} |
| 193 | + |
| 194 | +static int mipi_csi2rx_get_frmival(const struct device *dev, enum video_endpoint_id ep, |
| 195 | + struct video_frmival *frmival) |
| 196 | +{ |
| 197 | + const struct mipi_csi2rx_config *config = dev->config; |
| 198 | + |
| 199 | + return video_get_frmival(config->sensor_dev, ep, frmival); |
| 200 | +} |
| 201 | + |
| 202 | +static uint64_t mipi_csi2rx_cal_frame_size(const struct video_format *fmt) |
| 203 | +{ |
| 204 | + return fmt->height * fmt->width * video_pix_fmt_bpp(fmt->pixelformat) * 8; |
| 205 | +} |
| 206 | + |
| 207 | +static uint64_t mipi_csi2rx_estimate_pixel_rate(const struct video_frmival *cur_fmival, |
| 208 | + const struct video_frmival *fie_frmival, |
| 209 | + const struct video_format *cur_format, |
| 210 | + const struct video_format *fie_format, |
| 211 | + uint64_t cur_pixel_rate, uint8_t laneNum) |
| 212 | +{ |
| 213 | + return mipi_csi2rx_cal_frame_size(cur_format) * fie_frmival->denominator * |
| 214 | + cur_fmival->numerator * cur_pixel_rate / |
| 215 | + (mipi_csi2rx_cal_frame_size(fie_format) * fie_frmival->numerator * |
| 216 | + cur_fmival->denominator); |
| 217 | +} |
| 218 | + |
| 219 | +static int mipi_csi2rx_enum_frmival(const struct device *dev, enum video_endpoint_id ep, |
| 220 | + struct video_frmival_enum *fie) |
| 221 | +{ |
| 222 | + const struct mipi_csi2rx_config *config = dev->config; |
| 223 | + struct mipi_csi2rx_data *drv_data = dev->data; |
| 224 | + int ret; |
| 225 | + uint64_t cur_pixel_rate, est_pixel_rate; |
| 226 | + struct video_frmival cur_frmival; |
| 227 | + struct video_format cur_fmt; |
| 228 | + |
| 229 | + ret = video_enum_frmival(config->sensor_dev, ep, fie); |
| 230 | + if (ret) { |
| 231 | + return ret; |
| 232 | + } |
| 233 | + |
| 234 | + ret = video_get_ctrl(config->sensor_dev, VIDEO_CID_PIXEL_RATE, &cur_pixel_rate); |
| 235 | + if (ret) { |
| 236 | + LOG_ERR("Cannot get sensor_dev pixel rate"); |
| 237 | + return ret; |
| 238 | + } |
| 239 | + |
| 240 | + ret = video_get_frmival(config->sensor_dev, ep, &cur_frmival); |
| 241 | + if (ret) { |
| 242 | + LOG_ERR("Cannot get sensor_dev frame rate"); |
| 243 | + return ret; |
| 244 | + } |
| 245 | + |
| 246 | + ret = video_get_format(config->sensor_dev, ep, &cur_fmt); |
| 247 | + if (ret) { |
| 248 | + LOG_ERR("Cannot get sensor_dev format"); |
| 249 | + return ret; |
| 250 | + } |
| 251 | + |
| 252 | + if (fie->type == VIDEO_FRMIVAL_TYPE_DISCRETE) { |
| 253 | + est_pixel_rate = mipi_csi2rx_estimate_pixel_rate( |
| 254 | + &cur_frmival, &fie->discrete, &cur_fmt, fie->format, cur_pixel_rate, |
| 255 | + drv_data->csi2rxConfig.laneNum); |
| 256 | + if (est_pixel_rate > MAX_SUPPORTED_PIXEL_RATE) { |
| 257 | + return -EINVAL; |
| 258 | + } |
| 259 | + |
| 260 | + } else { |
| 261 | + /* Check the lane rate of the lower bound framerate */ |
| 262 | + est_pixel_rate = mipi_csi2rx_estimate_pixel_rate( |
| 263 | + &cur_frmival, &fie->stepwise.min, &cur_fmt, fie->format, cur_pixel_rate, |
| 264 | + drv_data->csi2rxConfig.laneNum); |
| 265 | + if (est_pixel_rate > MAX_SUPPORTED_PIXEL_RATE) { |
| 266 | + return -EINVAL; |
| 267 | + } |
| 268 | + |
| 269 | + /* Check the lane rate of the upper bound framerate */ |
| 270 | + est_pixel_rate = mipi_csi2rx_estimate_pixel_rate( |
| 271 | + &cur_frmival, &fie->stepwise.max, &cur_fmt, fie->format, cur_pixel_rate, |
| 272 | + drv_data->csi2rxConfig.laneNum); |
| 273 | + if (est_pixel_rate > MAX_SUPPORTED_PIXEL_RATE) { |
| 274 | + fie->stepwise.max.denominator = |
| 275 | + (mipi_csi2rx_cal_frame_size(&cur_fmt) * MAX_SUPPORTED_PIXEL_RATE * |
| 276 | + cur_frmival.denominator) / |
| 277 | + (mipi_csi2rx_cal_frame_size(fie->format) * cur_pixel_rate * |
| 278 | + cur_frmival.numerator); |
| 279 | + fie->stepwise.max.numerator = 1; |
| 280 | + } |
| 281 | + } |
| 282 | + |
| 283 | + return 0; |
| 284 | +} |
| 285 | + |
176 | 286 | static const struct video_driver_api mipi_csi2rx_driver_api = {
|
177 | 287 | .get_caps = mipi_csi2rx_get_caps,
|
178 | 288 | .get_format = mipi_csi2rx_get_fmt,
|
179 | 289 | .set_format = mipi_csi2rx_set_fmt,
|
180 | 290 | .stream_start = mipi_csi2rx_stream_start,
|
181 | 291 | .stream_stop = mipi_csi2rx_stream_stop,
|
182 | 292 | .set_ctrl = mipi_csi2rx_set_ctrl,
|
| 293 | + .set_frmival = mipi_csi2rx_set_frmival, |
| 294 | + .get_frmival = mipi_csi2rx_get_frmival, |
| 295 | + .enum_frmival = mipi_csi2rx_enum_frmival, |
183 | 296 | };
|
184 | 297 |
|
185 | 298 | static int mipi_csi2rx_init(const struct device *dev)
|
|
0 commit comments