|
8 | 8 |
|
9 | 9 | #include <zephyr/drivers/clock_control.h>
|
10 | 10 | #include <zephyr/drivers/video.h>
|
| 11 | +#include <zephyr/drivers/video-controls.h> |
11 | 12 | #include <zephyr/kernel.h>
|
12 | 13 | #include <zephyr/logging/log.h>
|
13 | 14 | #include <soc.h>
|
@@ -201,13 +202,125 @@ static inline int mipi_csi2rx_set_ctrl(const struct device *dev, unsigned int ci
|
201 | 202 | return -ENOTSUP;
|
202 | 203 | }
|
203 | 204 |
|
| 205 | +static int mipi_csi2rx_set_frmival(const struct device *dev, enum video_endpoint_id ep, |
| 206 | + struct video_frmival *frmival) |
| 207 | +{ |
| 208 | + const struct mipi_csi2rx_config *config = dev->config; |
| 209 | + int ret; |
| 210 | + |
| 211 | + ret = video_set_frmival(config->sensor_dev, ep, frmival); |
| 212 | + if (ret) { |
| 213 | + LOG_ERR("Cannot set sensor_dev frmival"); |
| 214 | + return ret; |
| 215 | + } |
| 216 | + |
| 217 | + ret = mipi_csi2rx_update_settings(dev, ep); |
| 218 | + |
| 219 | + return ret; |
| 220 | +} |
| 221 | + |
| 222 | +static int mipi_csi2rx_get_frmival(const struct device *dev, enum video_endpoint_id ep, |
| 223 | + struct video_frmival *frmival) |
| 224 | +{ |
| 225 | + const struct mipi_csi2rx_config *config = dev->config; |
| 226 | + |
| 227 | + return video_get_frmival(config->sensor_dev, ep, frmival); |
| 228 | +} |
| 229 | + |
| 230 | +static uint64_t mipi_csi2rx_cal_frame_size(const struct video_format *fmt) |
| 231 | +{ |
| 232 | + return fmt->height * fmt->width * video_pix_fmt_bpp(fmt->pixelformat) * 8; |
| 233 | +} |
| 234 | + |
| 235 | +static uint64_t mipi_csi2rx_estimate_pixel_rate(const struct video_frmival *cur_fmival, |
| 236 | + const struct video_frmival *fie_frmival, |
| 237 | + const struct video_format *cur_format, |
| 238 | + const struct video_format *fie_format, |
| 239 | + uint64_t cur_pixel_rate, uint8_t laneNum) |
| 240 | +{ |
| 241 | + return mipi_csi2rx_cal_frame_size(cur_format) * fie_frmival->denominator * |
| 242 | + cur_fmival->numerator * cur_pixel_rate / |
| 243 | + (mipi_csi2rx_cal_frame_size(fie_format) * fie_frmival->numerator * |
| 244 | + cur_fmival->denominator); |
| 245 | +} |
| 246 | + |
| 247 | +static int mipi_csi2rx_enum_frmival(const struct device *dev, enum video_endpoint_id ep, |
| 248 | + struct video_frmival_enum *fie) |
| 249 | +{ |
| 250 | + const struct mipi_csi2rx_config *config = dev->config; |
| 251 | + struct mipi_csi2rx_data *drv_data = dev->data; |
| 252 | + int ret; |
| 253 | + uint64_t cur_pixel_rate, est_pixel_rate; |
| 254 | + struct video_frmival cur_frmival; |
| 255 | + struct video_format cur_fmt; |
| 256 | + |
| 257 | + ret = video_enum_frmival(config->sensor_dev, ep, fie); |
| 258 | + if (ret) { |
| 259 | + return ret; |
| 260 | + } |
| 261 | + |
| 262 | + ret = video_get_ctrl(config->sensor_dev, VIDEO_CID_PIXEL_RATE, &cur_pixel_rate); |
| 263 | + if (ret) { |
| 264 | + LOG_ERR("Cannot get sensor_dev pixel rate"); |
| 265 | + return ret; |
| 266 | + } |
| 267 | + |
| 268 | + ret = video_get_frmival(config->sensor_dev, ep, &cur_frmival); |
| 269 | + if (ret) { |
| 270 | + LOG_ERR("Cannot get sensor_dev frame rate"); |
| 271 | + return ret; |
| 272 | + } |
| 273 | + |
| 274 | + ret = video_get_format(config->sensor_dev, ep, &cur_fmt); |
| 275 | + if (ret) { |
| 276 | + LOG_ERR("Cannot get sensor_dev format"); |
| 277 | + return ret; |
| 278 | + } |
| 279 | + |
| 280 | + if (fie->type == VIDEO_FRMIVAL_TYPE_DISCRETE) { |
| 281 | + est_pixel_rate = mipi_csi2rx_estimate_pixel_rate( |
| 282 | + &cur_frmival, &fie->discrete, &cur_fmt, fie->format, cur_pixel_rate, |
| 283 | + drv_data->csi2rxConfig.laneNum); |
| 284 | + if (est_pixel_rate > MAX_SUPPORTED_PIXEL_RATE) { |
| 285 | + return -EINVAL; |
| 286 | + } |
| 287 | + |
| 288 | + } else { |
| 289 | + /* Check the lane rate of the lower bound framerate */ |
| 290 | + est_pixel_rate = mipi_csi2rx_estimate_pixel_rate( |
| 291 | + &cur_frmival, &fie->stepwise.min, &cur_fmt, fie->format, cur_pixel_rate, |
| 292 | + drv_data->csi2rxConfig.laneNum); |
| 293 | + if (est_pixel_rate > MAX_SUPPORTED_PIXEL_RATE) { |
| 294 | + return -EINVAL; |
| 295 | + } |
| 296 | + |
| 297 | + /* Check the lane rate of the upper bound framerate */ |
| 298 | + est_pixel_rate = mipi_csi2rx_estimate_pixel_rate( |
| 299 | + &cur_frmival, &fie->stepwise.max, &cur_fmt, fie->format, cur_pixel_rate, |
| 300 | + drv_data->csi2rxConfig.laneNum); |
| 301 | + if (est_pixel_rate > MAX_SUPPORTED_PIXEL_RATE) { |
| 302 | + fie->stepwise.max.denominator = |
| 303 | + (mipi_csi2rx_cal_frame_size(&cur_fmt) * MAX_SUPPORTED_PIXEL_RATE * |
| 304 | + cur_frmival.denominator) / |
| 305 | + (mipi_csi2rx_cal_frame_size(fie->format) * cur_pixel_rate * |
| 306 | + cur_frmival.numerator); |
| 307 | + fie->stepwise.max.numerator = 1; |
| 308 | + } |
| 309 | + } |
| 310 | + |
| 311 | + return 0; |
| 312 | +} |
| 313 | + |
204 | 314 | static const struct video_driver_api mipi_csi2rx_driver_api = {
|
205 | 315 | .get_caps = mipi_csi2rx_get_caps,
|
206 | 316 | .get_format = mipi_csi2rx_get_fmt,
|
207 | 317 | .set_format = mipi_csi2rx_set_fmt,
|
208 | 318 | .stream_start = mipi_csi2rx_stream_start,
|
209 | 319 | .stream_stop = mipi_csi2rx_stream_stop,
|
210 | 320 | .set_ctrl = mipi_csi2rx_set_ctrl,
|
| 321 | + .set_frmival = mipi_csi2rx_set_frmival, |
| 322 | + .get_frmival = mipi_csi2rx_get_frmival, |
| 323 | + .enum_frmival = mipi_csi2rx_enum_frmival, |
211 | 324 | };
|
212 | 325 |
|
213 | 326 | static int mipi_csi2rx_init(const struct device *dev)
|
|
0 commit comments