starfive: add new target for StarFive JH7100/7110 SoC
[openwrt/staging/981213.git] / target / linux / starfive / patches-6.1 / 0085-media-starfive-Add-ISP-driver.patch
1 From 3b814965133cd53b1f30a34e4425294726cb0087 Mon Sep 17 00:00:00 2001
2 From: Jack Zhu <jack.zhu@starfivetech.com>
3 Date: Fri, 12 May 2023 18:28:43 +0800
4 Subject: [PATCH 085/122] media: starfive: Add ISP driver
5
6 Add ISP driver for StarFive Camera Subsystem.
7
8 Signed-off-by: Jack Zhu <jack.zhu@starfivetech.com>
9 ---
10 drivers/media/platform/starfive/Makefile | 2 +
11 drivers/media/platform/starfive/stf_camss.c | 71 ++-
12 drivers/media/platform/starfive/stf_camss.h | 2 +
13 drivers/media/platform/starfive/stf_isp.c | 550 ++++++++++++++++++
14 drivers/media/platform/starfive/stf_isp.h | 476 +++++++++++++++
15 .../media/platform/starfive/stf_isp_hw_ops.c | 452 ++++++++++++++
16 6 files changed, 1551 insertions(+), 2 deletions(-)
17 create mode 100644 drivers/media/platform/starfive/stf_isp.c
18 create mode 100644 drivers/media/platform/starfive/stf_isp.h
19 create mode 100644 drivers/media/platform/starfive/stf_isp_hw_ops.c
20
21 --- a/drivers/media/platform/starfive/Makefile
22 +++ b/drivers/media/platform/starfive/Makefile
23 @@ -5,6 +5,8 @@
24
25 starfive-camss-objs += \
26 stf_camss.o \
27 + stf_isp.o \
28 + stf_isp_hw_ops.o \
29 stf_video.o
30
31 obj-$(CONFIG_VIDEO_STARFIVE_CAMSS) += starfive-camss.o \
32 --- a/drivers/media/platform/starfive/stf_camss.c
33 +++ b/drivers/media/platform/starfive/stf_camss.c
34 @@ -126,16 +126,66 @@ err_cleanup:
35 return ret;
36 }
37
38 +/*
39 + * stfcamss_init_subdevices - Initialize subdev structures and resources
40 + * @stfcamss: STFCAMSS device
41 + *
42 + * Return 0 on success or a negative error code on failure
43 + */
44 +static int stfcamss_init_subdevices(struct stfcamss *stfcamss)
45 +{
46 + int ret;
47 +
48 + ret = stf_isp_subdev_init(stfcamss);
49 + if (ret < 0) {
50 + dev_err(stfcamss->dev, "Failed to init isp subdev: %d\n", ret);
51 + return ret;
52 + }
53 +
54 + return ret;
55 +}
56 +
57 +static int stfcamss_register_subdevices(struct stfcamss *stfcamss)
58 +{
59 + int ret;
60 + struct stf_isp_dev *isp_dev = &stfcamss->isp_dev;
61 +
62 + ret = stf_isp_register(isp_dev, &stfcamss->v4l2_dev);
63 + if (ret < 0) {
64 + dev_err(stfcamss->dev,
65 + "Failed to register stf isp%d entity: %d\n", 0, ret);
66 + return ret;
67 + }
68 +
69 + return ret;
70 +}
71 +
72 +static void stfcamss_unregister_subdevices(struct stfcamss *stfcamss)
73 +{
74 + stf_isp_unregister(&stfcamss->isp_dev);
75 +}
76 +
77 static int stfcamss_subdev_notifier_bound(struct v4l2_async_notifier *async,
78 struct v4l2_subdev *subdev,
79 struct v4l2_async_subdev *asd)
80 {
81 struct stfcamss *stfcamss =
82 container_of(async, struct stfcamss, notifier);
83 + struct stfcamss_async_subdev *csd =
84 + container_of(asd, struct stfcamss_async_subdev, asd);
85 + enum port_num port = csd->port;
86 + struct stf_isp_dev *isp_dev = &stfcamss->isp_dev;
87 struct host_data *host_data = &stfcamss->host_data;
88 struct media_entity *source;
89 int i, j;
90
91 + if (port == PORT_NUMBER_CSI2RX) {
92 + host_data->host_entity[1] = &isp_dev->subdev.entity;
93 + } else if (port == PORT_NUMBER_DVP_SENSOR) {
94 + dev_err(stfcamss->dev, "Not support DVP sensor\n");
95 + return -EPERM;
96 + }
97 +
98 source = &subdev->entity;
99
100 for (i = 0; i < source->num_pads; i++) {
101 @@ -266,12 +316,18 @@ static int stfcamss_probe(struct platfor
102 return -ENODEV;
103 }
104
105 + ret = stfcamss_init_subdevices(stfcamss);
106 + if (ret < 0) {
107 + dev_err(dev, "Failed to init subdevice: %d\n", ret);
108 + goto err_cleanup_notifier;
109 + }
110 +
111 stfcamss_mc_init(pdev, stfcamss);
112
113 ret = v4l2_device_register(stfcamss->dev, &stfcamss->v4l2_dev);
114 if (ret < 0) {
115 dev_err(dev, "Failed to register V4L2 device: %d\n", ret);
116 - goto err_cleanup_notifier;
117 + goto err_cleanup_media_device;
118 }
119
120 ret = media_device_register(&stfcamss->media_dev);
121 @@ -280,22 +336,32 @@ static int stfcamss_probe(struct platfor
122 goto err_unregister_device;
123 }
124
125 + ret = stfcamss_register_subdevices(stfcamss);
126 + if (ret < 0) {
127 + dev_err(dev, "Failed to register subdevice: %d\n", ret);
128 + goto err_unregister_media_dev;
129 + }
130 +
131 stfcamss->notifier.ops = &stfcamss_subdev_notifier_ops;
132 ret = v4l2_async_nf_register(&stfcamss->v4l2_dev, &stfcamss->notifier);
133 if (ret) {
134 dev_err(dev, "Failed to register async subdev nodes: %d\n",
135 ret);
136 - goto err_unregister_media_dev;
137 + goto err_unregister_subdevs;
138 }
139
140 pm_runtime_enable(dev);
141
142 return 0;
143
144 +err_unregister_subdevs:
145 + stfcamss_unregister_subdevices(stfcamss);
146 err_unregister_media_dev:
147 media_device_unregister(&stfcamss->media_dev);
148 err_unregister_device:
149 v4l2_device_unregister(&stfcamss->v4l2_dev);
150 +err_cleanup_media_device:
151 + media_device_cleanup(&stfcamss->media_dev);
152 err_cleanup_notifier:
153 v4l2_async_nf_cleanup(&stfcamss->notifier);
154 return ret;
155 @@ -311,6 +377,7 @@ static int stfcamss_remove(struct platfo
156 {
157 struct stfcamss *stfcamss = platform_get_drvdata(pdev);
158
159 + stfcamss_unregister_subdevices(stfcamss);
160 v4l2_device_unregister(&stfcamss->v4l2_dev);
161 media_device_cleanup(&stfcamss->media_dev);
162 pm_runtime_disable(&pdev->dev);
163 --- a/drivers/media/platform/starfive/stf_camss.h
164 +++ b/drivers/media/platform/starfive/stf_camss.h
165 @@ -16,6 +16,7 @@
166 #include <media/v4l2-device.h>
167
168 #include "stf_common.h"
169 +#include "stf_isp.h"
170
171 #define DRV_NAME "starfive-camss"
172 #define STF_DVP_NAME "stf_dvp"
173 @@ -71,6 +72,7 @@ struct stfcamss {
174 struct media_device media_dev;
175 struct media_pipeline pipe;
176 struct device *dev;
177 + struct stf_isp_dev isp_dev;
178 struct v4l2_async_notifier notifier;
179 struct host_data host_data;
180 void __iomem *syscon_base;
181 --- /dev/null
182 +++ b/drivers/media/platform/starfive/stf_isp.c
183 @@ -0,0 +1,550 @@
184 +// SPDX-License-Identifier: GPL-2.0
185 +/*
186 + * stf_isp.c
187 + *
188 + * StarFive Camera Subsystem - ISP Module
189 + *
190 + * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
191 + */
192 +#include <linux/firmware.h>
193 +#include <media/v4l2-event.h>
194 +
195 +#include "stf_camss.h"
196 +
197 +#define SINK_FORMATS_INDEX 0
198 +#define UO_FORMATS_INDEX 1
199 +
200 +static int isp_set_selection(struct v4l2_subdev *sd,
201 + struct v4l2_subdev_state *state,
202 + struct v4l2_subdev_selection *sel);
203 +
204 +static const struct isp_format isp_formats_sink[] = {
205 + { MEDIA_BUS_FMT_SRGGB10_1X10, 10 },
206 + { MEDIA_BUS_FMT_SGRBG10_1X10, 10 },
207 + { MEDIA_BUS_FMT_SGBRG10_1X10, 10 },
208 + { MEDIA_BUS_FMT_SBGGR10_1X10, 10 },
209 +};
210 +
211 +static const struct isp_format isp_formats_uo[] = {
212 + { MEDIA_BUS_FMT_Y12_1X12, 8 },
213 +};
214 +
215 +static const struct isp_format_table isp_formats_st7110[] = {
216 + { isp_formats_sink, ARRAY_SIZE(isp_formats_sink) },
217 + { isp_formats_uo, ARRAY_SIZE(isp_formats_uo) },
218 +};
219 +
220 +int stf_isp_subdev_init(struct stfcamss *stfcamss)
221 +{
222 + struct stf_isp_dev *isp_dev = &stfcamss->isp_dev;
223 +
224 + isp_dev->sdev_type = STF_SUBDEV_TYPE_ISP;
225 + isp_dev->stfcamss = stfcamss;
226 + isp_dev->formats = isp_formats_st7110;
227 + isp_dev->nformats = ARRAY_SIZE(isp_formats_st7110);
228 +
229 + mutex_init(&isp_dev->stream_lock);
230 + mutex_init(&isp_dev->power_lock);
231 + return 0;
232 +}
233 +
234 +static int isp_set_power(struct v4l2_subdev *sd, int on)
235 +{
236 + struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
237 +
238 + mutex_lock(&isp_dev->power_lock);
239 + if (on) {
240 + if (isp_dev->power_count == 0)
241 + dev_dbg(isp_dev->stfcamss->dev, "turn on isp\n");
242 + isp_dev->power_count++;
243 + } else {
244 + if (isp_dev->power_count == 0)
245 + goto exit;
246 + isp_dev->power_count--;
247 + }
248 +exit:
249 + mutex_unlock(&isp_dev->power_lock);
250 +
251 + return 0;
252 +}
253 +
254 +static struct v4l2_mbus_framefmt *
255 +__isp_get_format(struct stf_isp_dev *isp_dev,
256 + struct v4l2_subdev_state *state,
257 + unsigned int pad,
258 + enum v4l2_subdev_format_whence which)
259 +{
260 + if (which == V4L2_SUBDEV_FORMAT_TRY)
261 + return v4l2_subdev_get_try_format(&isp_dev->subdev, state, pad);
262 +
263 + return &isp_dev->fmt[pad];
264 +}
265 +
266 +static int isp_set_stream(struct v4l2_subdev *sd, int enable)
267 +{
268 + struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
269 + int ret = 0;
270 + struct v4l2_mbus_framefmt *fmt;
271 + struct v4l2_event src_ch = { 0 };
272 +
273 + fmt = __isp_get_format(isp_dev, NULL, STF_ISP_PAD_SINK,
274 + V4L2_SUBDEV_FORMAT_ACTIVE);
275 + mutex_lock(&isp_dev->stream_lock);
276 + if (enable) {
277 + if (isp_dev->stream_count == 0) {
278 + stf_isp_clk_enable(isp_dev);
279 + stf_isp_reset(isp_dev);
280 + stf_isp_init_cfg(isp_dev);
281 + stf_isp_settings(isp_dev, isp_dev->rect, fmt->code);
282 + stf_isp_stream_set(isp_dev);
283 + }
284 + isp_dev->stream_count++;
285 + } else {
286 + if (isp_dev->stream_count == 0)
287 + goto exit;
288 +
289 + if (isp_dev->stream_count == 1)
290 + stf_isp_clk_disable(isp_dev);
291 +
292 + isp_dev->stream_count--;
293 + }
294 + src_ch.type = V4L2_EVENT_SOURCE_CHANGE,
295 + src_ch.u.src_change.changes = isp_dev->stream_count,
296 +
297 + v4l2_subdev_notify_event(sd, &src_ch);
298 +exit:
299 + mutex_unlock(&isp_dev->stream_lock);
300 +
301 + return ret;
302 +}
303 +
304 +static void isp_try_format(struct stf_isp_dev *isp_dev,
305 + struct v4l2_subdev_state *state,
306 + unsigned int pad,
307 + struct v4l2_mbus_framefmt *fmt,
308 + enum v4l2_subdev_format_whence which)
309 +{
310 + const struct isp_format_table *formats;
311 + struct stf_isp_crop *rect;
312 + int i;
313 +
314 + switch (pad) {
315 + case STF_ISP_PAD_SINK:
316 + /* Set format on sink pad */
317 + formats = &isp_dev->formats[SINK_FORMATS_INDEX];
318 + rect = &isp_dev->rect[SINK_FORMATS_INDEX];
319 + fmt->width = clamp_t(u32,
320 + fmt->width, STFCAMSS_FRAME_MIN_WIDTH,
321 + STFCAMSS_FRAME_MAX_WIDTH);
322 + fmt->height = clamp_t(u32,
323 + fmt->height, STFCAMSS_FRAME_MIN_HEIGHT,
324 + STFCAMSS_FRAME_MAX_HEIGHT);
325 + fmt->height &= ~0x1;
326 + fmt->field = V4L2_FIELD_NONE;
327 + fmt->colorspace = V4L2_COLORSPACE_SRGB;
328 + fmt->flags = 0;
329 + break;
330 +
331 + case STF_ISP_PAD_SRC:
332 + formats = &isp_dev->formats[UO_FORMATS_INDEX];
333 + rect = &isp_dev->rect[UO_FORMATS_INDEX];
334 + *fmt = *__isp_get_format(isp_dev, state,
335 + STF_ISP_PAD_SINK, which);
336 + break;
337 + }
338 +
339 + for (i = 0; i < formats->nfmts; i++) {
340 + if (fmt->code == formats->fmts[i].code)
341 + break;
342 + }
343 +
344 + if (i >= formats->nfmts) {
345 + fmt->code = formats->fmts[0].code;
346 + rect->bpp = formats->fmts[0].bpp;
347 + } else {
348 + rect->bpp = formats->fmts[i].bpp;
349 + }
350 +}
351 +
352 +static int isp_enum_mbus_code(struct v4l2_subdev *sd,
353 + struct v4l2_subdev_state *state,
354 + struct v4l2_subdev_mbus_code_enum *code)
355 +{
356 + struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
357 + const struct isp_format_table *formats;
358 +
359 + if (code->index >= isp_dev->nformats)
360 + return -EINVAL;
361 + if (code->pad == STF_ISP_PAD_SINK) {
362 + formats = &isp_dev->formats[SINK_FORMATS_INDEX];
363 + code->code = formats->fmts[code->index].code;
364 + } else {
365 + struct v4l2_mbus_framefmt *sink_fmt;
366 +
367 + sink_fmt = __isp_get_format(isp_dev, state, STF_ISP_PAD_SINK,
368 + code->which);
369 +
370 + code->code = sink_fmt->code;
371 + if (!code->code)
372 + return -EINVAL;
373 + }
374 + code->flags = 0;
375 +
376 + return 0;
377 +}
378 +
379 +static int isp_enum_frame_size(struct v4l2_subdev *sd,
380 + struct v4l2_subdev_state *state,
381 + struct v4l2_subdev_frame_size_enum *fse)
382 +{
383 + struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
384 + struct v4l2_mbus_framefmt format;
385 +
386 + if (fse->index != 0)
387 + return -EINVAL;
388 +
389 + format.code = fse->code;
390 + format.width = 1;
391 + format.height = 1;
392 + isp_try_format(isp_dev, state, fse->pad, &format, fse->which);
393 + fse->min_width = format.width;
394 + fse->min_height = format.height;
395 +
396 + if (format.code != fse->code)
397 + return -EINVAL;
398 +
399 + format.code = fse->code;
400 + format.width = -1;
401 + format.height = -1;
402 + isp_try_format(isp_dev, state, fse->pad, &format, fse->which);
403 + fse->max_width = format.width;
404 + fse->max_height = format.height;
405 +
406 + return 0;
407 +}
408 +
409 +static int isp_get_format(struct v4l2_subdev *sd,
410 + struct v4l2_subdev_state *state,
411 + struct v4l2_subdev_format *fmt)
412 +{
413 + struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
414 + struct v4l2_mbus_framefmt *format;
415 +
416 + format = __isp_get_format(isp_dev, state, fmt->pad, fmt->which);
417 + if (!format)
418 + return -EINVAL;
419 +
420 + fmt->format = *format;
421 +
422 + return 0;
423 +}
424 +
425 +static int isp_set_format(struct v4l2_subdev *sd,
426 + struct v4l2_subdev_state *state,
427 + struct v4l2_subdev_format *fmt)
428 +{
429 + struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
430 + struct v4l2_mbus_framefmt *format;
431 +
432 + format = __isp_get_format(isp_dev, state, fmt->pad, fmt->which);
433 + if (!format)
434 + return -EINVAL;
435 +
436 + mutex_lock(&isp_dev->stream_lock);
437 +
438 + isp_try_format(isp_dev, state, fmt->pad, &fmt->format, fmt->which);
439 + *format = fmt->format;
440 +
441 + mutex_unlock(&isp_dev->stream_lock);
442 +
443 + /* Propagate to in crop */
444 + if (fmt->pad == STF_ISP_PAD_SINK) {
445 + struct v4l2_subdev_selection sel = { 0 };
446 + int ret;
447 +
448 + /* Reset sink pad compose selection */
449 + sel.which = fmt->which;
450 + sel.pad = STF_ISP_PAD_SINK;
451 + sel.target = V4L2_SEL_TGT_CROP;
452 + sel.r.width = fmt->format.width;
453 + sel.r.height = fmt->format.height;
454 + ret = isp_set_selection(sd, state, &sel);
455 + if (ret < 0)
456 + return ret;
457 + }
458 +
459 + return 0;
460 +}
461 +
462 +static struct v4l2_rect *
463 +__isp_get_crop(struct stf_isp_dev *isp_dev,
464 + struct v4l2_subdev_state *state,
465 + unsigned int pad,
466 + enum v4l2_subdev_format_whence which)
467 +{
468 + if (which == V4L2_SUBDEV_FORMAT_TRY)
469 + return v4l2_subdev_get_try_crop(&isp_dev->subdev, state,
470 + STF_ISP_PAD_SINK);
471 +
472 + return &isp_dev->rect[pad].rect;
473 +}
474 +
475 +static void isp_try_crop(struct stf_isp_dev *isp_dev,
476 + struct v4l2_subdev_state *state,
477 + struct v4l2_rect *rect,
478 + enum v4l2_subdev_format_whence which)
479 +{
480 + struct v4l2_mbus_framefmt *fmt;
481 +
482 + fmt = __isp_get_format(isp_dev, state, STF_ISP_PAD_SINK, which);
483 +
484 + if (rect->width > fmt->width)
485 + rect->width = fmt->width;
486 +
487 + if (rect->width + rect->left > fmt->width)
488 + rect->left = fmt->width - rect->width;
489 +
490 + if (rect->height > fmt->height)
491 + rect->height = fmt->height;
492 +
493 + if (rect->height + rect->top > fmt->height)
494 + rect->top = fmt->height - rect->height;
495 +
496 + if (rect->width < STFCAMSS_FRAME_MIN_WIDTH) {
497 + rect->left = 0;
498 + rect->width = STFCAMSS_FRAME_MAX_WIDTH;
499 + }
500 +
501 + if (rect->height < STFCAMSS_FRAME_MIN_HEIGHT) {
502 + rect->top = 0;
503 + rect->height = STFCAMSS_FRAME_MAX_HEIGHT;
504 + }
505 + rect->height &= ~0x1;
506 +}
507 +
508 +static int isp_get_selection(struct v4l2_subdev *sd,
509 + struct v4l2_subdev_state *state,
510 + struct v4l2_subdev_selection *sel)
511 +{
512 + struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
513 + struct v4l2_subdev_format fmt = { 0 };
514 + struct v4l2_rect *rect;
515 + int ret;
516 +
517 + switch (sel->target) {
518 + case V4L2_SEL_TGT_CROP_BOUNDS:
519 + if (sel->pad == STF_ISP_PAD_SINK) {
520 + fmt.pad = sel->pad;
521 + fmt.which = sel->which;
522 + ret = isp_get_format(sd, state, &fmt);
523 + if (ret < 0)
524 + return ret;
525 +
526 + sel->r.left = 0;
527 + sel->r.top = 0;
528 + sel->r.width = fmt.format.width;
529 + sel->r.height = fmt.format.height;
530 + } else if (sel->pad == STF_ISP_PAD_SRC) {
531 + rect = __isp_get_crop(isp_dev, state,
532 + sel->pad, sel->which);
533 + sel->r = *rect;
534 + }
535 + break;
536 +
537 + case V4L2_SEL_TGT_CROP:
538 + rect = __isp_get_crop(isp_dev, state, sel->pad, sel->which);
539 + if (!rect)
540 + return -EINVAL;
541 +
542 + sel->r = *rect;
543 + break;
544 +
545 + default:
546 + return -EINVAL;
547 + }
548 +
549 + return 0;
550 +}
551 +
552 +static int isp_set_selection(struct v4l2_subdev *sd,
553 + struct v4l2_subdev_state *state,
554 + struct v4l2_subdev_selection *sel)
555 +{
556 + struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
557 + struct v4l2_rect *rect;
558 + int ret = 0;
559 +
560 + if (sel->target == V4L2_SEL_TGT_CROP &&
561 + sel->pad == STF_ISP_PAD_SINK) {
562 + struct v4l2_subdev_selection crop = { 0 };
563 +
564 + rect = __isp_get_crop(isp_dev, state, sel->pad, sel->which);
565 + if (!rect)
566 + return -EINVAL;
567 +
568 + mutex_lock(&isp_dev->stream_lock);
569 + isp_try_crop(isp_dev, state, &sel->r, sel->which);
570 + *rect = sel->r;
571 + mutex_unlock(&isp_dev->stream_lock);
572 +
573 + /* Reset source crop selection */
574 + crop.which = sel->which;
575 + crop.pad = STF_ISP_PAD_SRC;
576 + crop.target = V4L2_SEL_TGT_CROP;
577 + crop.r = *rect;
578 + ret = isp_set_selection(sd, state, &crop);
579 + } else if (sel->target == V4L2_SEL_TGT_CROP &&
580 + sel->pad == STF_ISP_PAD_SRC) {
581 + struct v4l2_subdev_format fmt = { 0 };
582 +
583 + rect = __isp_get_crop(isp_dev, state, sel->pad, sel->which);
584 + if (!rect)
585 + return -EINVAL;
586 +
587 + mutex_lock(&isp_dev->stream_lock);
588 + isp_try_crop(isp_dev, state, &sel->r, sel->which);
589 + *rect = sel->r;
590 + mutex_unlock(&isp_dev->stream_lock);
591 +
592 + /* Reset source pad format width and height */
593 + fmt.which = sel->which;
594 + fmt.pad = STF_ISP_PAD_SRC;
595 + fmt.format.width = rect->width;
596 + fmt.format.height = rect->height;
597 + ret = isp_set_format(sd, state, &fmt);
598 + if (ret < 0)
599 + return ret;
600 + }
601 +
602 + dev_dbg(isp_dev->stfcamss->dev, "pad: %d sel(%d,%d)/%dx%d\n",
603 + sel->pad, sel->r.left, sel->r.top, sel->r.width, sel->r.height);
604 +
605 + return 0;
606 +}
607 +
608 +static int isp_init_formats(struct v4l2_subdev *sd,
609 + struct v4l2_subdev_fh *fh)
610 +{
611 + struct v4l2_subdev_format format = {
612 + .pad = STF_ISP_PAD_SINK,
613 + .which =
614 + fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE,
615 + .format = {
616 + .code = MEDIA_BUS_FMT_RGB565_2X8_LE,
617 + .width = 1920,
618 + .height = 1080
619 + }
620 + };
621 +
622 + return isp_set_format(sd, fh ? fh->state : NULL, &format);
623 +}
624 +
625 +static int isp_link_setup(struct media_entity *entity,
626 + const struct media_pad *local,
627 + const struct media_pad *remote, u32 flags)
628 +{
629 + if (flags & MEDIA_LNK_FL_ENABLED)
630 + if (media_pad_remote_pad_first(local))
631 + return -EBUSY;
632 + return 0;
633 +}
634 +
635 +static int stf_isp_subscribe_event(struct v4l2_subdev *sd,
636 + struct v4l2_fh *fh,
637 + struct v4l2_event_subscription *sub)
638 +{
639 + switch (sub->type) {
640 + case V4L2_EVENT_SOURCE_CHANGE:
641 + return v4l2_src_change_event_subdev_subscribe(sd, fh, sub);
642 + default:
643 + return -EINVAL;
644 + }
645 +}
646 +
647 +static const struct v4l2_subdev_core_ops isp_core_ops = {
648 + .s_power = isp_set_power,
649 + .subscribe_event = stf_isp_subscribe_event,
650 + .unsubscribe_event = v4l2_event_subdev_unsubscribe,
651 +};
652 +
653 +static const struct v4l2_subdev_video_ops isp_video_ops = {
654 + .s_stream = isp_set_stream,
655 +};
656 +
657 +static const struct v4l2_subdev_pad_ops isp_pad_ops = {
658 + .enum_mbus_code = isp_enum_mbus_code,
659 + .enum_frame_size = isp_enum_frame_size,
660 + .get_fmt = isp_get_format,
661 + .set_fmt = isp_set_format,
662 + .get_selection = isp_get_selection,
663 + .set_selection = isp_set_selection,
664 +};
665 +
666 +static const struct v4l2_subdev_ops isp_v4l2_ops = {
667 + .core = &isp_core_ops,
668 + .video = &isp_video_ops,
669 + .pad = &isp_pad_ops,
670 +};
671 +
672 +static const struct v4l2_subdev_internal_ops isp_v4l2_internal_ops = {
673 + .open = isp_init_formats,
674 +};
675 +
676 +static const struct media_entity_operations isp_media_ops = {
677 + .link_setup = isp_link_setup,
678 + .link_validate = v4l2_subdev_link_validate,
679 +};
680 +
681 +int stf_isp_register(struct stf_isp_dev *isp_dev, struct v4l2_device *v4l2_dev)
682 +{
683 + struct v4l2_subdev *sd = &isp_dev->subdev;
684 + struct media_pad *pads = isp_dev->pads;
685 + int ret;
686 +
687 + v4l2_subdev_init(sd, &isp_v4l2_ops);
688 + sd->internal_ops = &isp_v4l2_internal_ops;
689 + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
690 + snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d", STF_ISP_NAME, 0);
691 + v4l2_set_subdevdata(sd, isp_dev);
692 +
693 + ret = isp_init_formats(sd, NULL);
694 + if (ret < 0) {
695 + dev_err(isp_dev->stfcamss->dev, "Failed to init format: %d\n",
696 + ret);
697 + return ret;
698 + }
699 +
700 + pads[STF_ISP_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
701 + pads[STF_ISP_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE;
702 +
703 + sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
704 + sd->entity.ops = &isp_media_ops;
705 + ret = media_entity_pads_init(&sd->entity, STF_ISP_PAD_MAX, pads);
706 + if (ret < 0) {
707 + dev_err(isp_dev->stfcamss->dev,
708 + "Failed to init media entity: %d\n", ret);
709 + return ret;
710 + }
711 +
712 + ret = v4l2_device_register_subdev(v4l2_dev, sd);
713 + if (ret < 0) {
714 + dev_err(isp_dev->stfcamss->dev,
715 + "Failed to register subdev: %d\n", ret);
716 + goto err_sreg;
717 + }
718 +
719 + return 0;
720 +
721 +err_sreg:
722 + media_entity_cleanup(&sd->entity);
723 + return ret;
724 +}
725 +
726 +int stf_isp_unregister(struct stf_isp_dev *isp_dev)
727 +{
728 + v4l2_device_unregister_subdev(&isp_dev->subdev);
729 + media_entity_cleanup(&isp_dev->subdev.entity);
730 + mutex_destroy(&isp_dev->stream_lock);
731 + mutex_destroy(&isp_dev->power_lock);
732 + return 0;
733 +}
734 --- /dev/null
735 +++ b/drivers/media/platform/starfive/stf_isp.h
736 @@ -0,0 +1,476 @@
737 +/* SPDX-License-Identifier: GPL-2.0 */
738 +/*
739 + * stf_isp.h
740 + *
741 + * StarFive Camera Subsystem - ISP Module
742 + *
743 + * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
744 + */
745 +
746 +#ifndef STF_ISP_H
747 +#define STF_ISP_H
748 +
749 +#include <media/media-entity.h>
750 +#include <media/v4l2-subdev.h>
751 +
752 +#include "stf_video.h"
753 +
754 +#define ISP_RAW_DATA_BITS 12
755 +#define SCALER_RATIO_MAX 1
756 +#define STF_ISP_REG_OFFSET_MAX 0x0fff
757 +#define STF_ISP_REG_DELAY_MAX 100
758 +
759 +/* isp registers */
760 +#define ISP_REG_CSI_INPUT_EN_AND_STATUS 0x000
761 +#define CSI_SCD_ERR BIT(6)
762 +#define CSI_ITU656_ERR BIT(4)
763 +#define CSI_ITU656_F BIT(3)
764 +#define CSI_SCD_DONE BIT(2)
765 +#define CSI_BUSY_S BIT(1)
766 +#define CSI_EN_S BIT(0)
767 +
768 +#define ISP_REG_CSIINTS 0x008
769 +#define CSI_INTS(n) ((n) << 16)
770 +#define CSI_SHA_M(n) ((n) << 0)
771 +#define CSI_INTS_MASK GENMASK(17, 16)
772 +
773 +#define ISP_REG_CSI_MODULE_CFG 0x010
774 +#define CSI_DUMP_EN BIT(19)
775 +#define CSI_VS_EN BIT(18)
776 +#define CSI_SC_EN BIT(17)
777 +#define CSI_OBA_EN BIT(16)
778 +#define CSI_AWB_EN BIT(7)
779 +#define CSI_LCCF_EN BIT(6)
780 +#define CSI_OECFHM_EN BIT(5)
781 +#define CSI_OECF_EN BIT(4)
782 +#define CSI_LCBQ_EN BIT(3)
783 +#define CSI_OBC_EN BIT(2)
784 +#define CSI_DEC_EN BIT(1)
785 +#define CSI_DC_EN BIT(0)
786 +
787 +#define ISP_REG_SENSOR 0x014
788 +#define DVP_SYNC_POL(n) ((n) << 2)
789 +#define ITU656_EN(n) ((n) << 1)
790 +#define IMAGER_SEL(n) ((n) << 0)
791 +
792 +#define ISP_REG_RAW_FORMAT_CFG 0x018
793 +#define SMY13(n) ((n) << 14)
794 +#define SMY12(n) ((n) << 12)
795 +#define SMY11(n) ((n) << 10)
796 +#define SMY10(n) ((n) << 8)
797 +#define SMY3(n) ((n) << 6)
798 +#define SMY2(n) ((n) << 4)
799 +#define SMY1(n) ((n) << 2)
800 +#define SMY0(n) ((n) << 0)
801 +
802 +#define ISP_REG_PIC_CAPTURE_START_CFG 0x01c
803 +#define VSTART_CAP(n) ((n) << 16)
804 +#define HSTART_CAP(n) ((n) << 0)
805 +
806 +#define ISP_REG_PIC_CAPTURE_END_CFG 0x020
807 +#define VEND_CAP(n) ((n) << 16)
808 +#define HEND_CAP(n) ((n) << 0)
809 +
810 +#define ISP_REG_DUMP_CFG_0 0x024
811 +#define ISP_REG_DUMP_CFG_1 0x028
812 +#define DUMP_ID(n) ((n) << 24)
813 +#define DUMP_SHT(n) ((n) << 20)
814 +#define DUMP_BURST_LEN(n) ((n) << 16)
815 +#define DUMP_SD(n) ((n) << 0)
816 +#define DUMP_BURST_LEN_MASK GENMASK(17, 16)
817 +#define DUMP_SD_MASK GENMASK(15, 0)
818 +
819 +#define ISP_REG_DEC_CFG 0x030
820 +#define DEC_V_KEEP(n) ((n) << 24)
821 +#define DEC_V_PERIOD(n) ((n) << 16)
822 +#define DEC_H_KEEP(n) ((n) << 8)
823 +#define DEC_H_PERIOD(n) ((n) << 0)
824 +
825 +#define ISP_REG_OBC_CFG 0x034
826 +#define OBC_W_H(y) ((y) << 4)
827 +#define OBC_W_W(x) ((x) << 0)
828 +
829 +#define ISP_REG_DC_CFG_1 0x044
830 +#define DC_AXI_ID(n) ((n) << 0)
831 +
832 +#define ISP_REG_LCCF_CFG_0 0x050
833 +#define Y_DISTANCE(y) ((y) << 16)
834 +#define X_DISTANCE(x) ((x) << 16)
835 +
836 +#define ISP_REG_LCCF_CFG_1 0x058
837 +#define LCCF_MAX_DIS(n) ((n) << 0)
838 +
839 +#define ISP_REG_LCBQ_CFG_0 0x074
840 +#define H_LCBQ(y) ((y) << 12)
841 +#define W_LCBQ(x) ((x) << 8)
842 +
843 +#define ISP_REG_LCBQ_CFG_1 0x07c
844 +#define Y_COOR(y) ((y) << 16)
845 +#define X_COOR(x) ((x) << 0)
846 +
847 +#define ISP_REG_OECF_X0_CFG0 0x100
848 +#define ISP_REG_OECF_X0_CFG1 0x104
849 +#define ISP_REG_OECF_X0_CFG2 0x108
850 +#define ISP_REG_OECF_X0_CFG3 0x10c
851 +#define ISP_REG_OECF_X0_CFG4 0x110
852 +#define ISP_REG_OECF_X0_CFG5 0x114
853 +#define ISP_REG_OECF_X0_CFG6 0x118
854 +#define ISP_REG_OECF_X0_CFG7 0x11c
855 +
856 +#define ISP_REG_OECF_Y3_CFG0 0x1e0
857 +#define ISP_REG_OECF_Y3_CFG1 0x1e4
858 +#define ISP_REG_OECF_Y3_CFG2 0x1e8
859 +#define ISP_REG_OECF_Y3_CFG3 0x1ec
860 +#define ISP_REG_OECF_Y3_CFG4 0x1f0
861 +#define ISP_REG_OECF_Y3_CFG5 0x1f4
862 +#define ISP_REG_OECF_Y3_CFG6 0x1f8
863 +#define ISP_REG_OECF_Y3_CFG7 0x1fc
864 +
865 +#define ISP_REG_OECF_S0_CFG0 0x200
866 +#define ISP_REG_OECF_S3_CFG7 0x27c
867 +#define OCEF_PAR_H(n) ((n) << 16)
868 +#define OCEF_PAR_L(n) ((n) << 0)
869 +
870 +#define ISP_REG_AWB_X0_CFG_0 0x280
871 +#define ISP_REG_AWB_X0_CFG_1 0x284
872 +#define ISP_REG_AWB_X1_CFG_0 0x288
873 +#define ISP_REG_AWB_X1_CFG_1 0x28c
874 +#define ISP_REG_AWB_X2_CFG_0 0x290
875 +#define ISP_REG_AWB_X2_CFG_1 0x294
876 +#define ISP_REG_AWB_X3_CFG_0 0x298
877 +#define ISP_REG_AWB_X3_CFG_1 0x29c
878 +#define AWB_X_SYMBOL_H(n) ((n) << 16)
879 +#define AWB_X_SYMBOL_L(n) ((n) << 0)
880 +
881 +#define ISP_REG_AWB_Y0_CFG_0 0x2a0
882 +#define ISP_REG_AWB_Y0_CFG_1 0x2a4
883 +#define ISP_REG_AWB_Y1_CFG_0 0x2a8
884 +#define ISP_REG_AWB_Y1_CFG_1 0x2ac
885 +#define ISP_REG_AWB_Y2_CFG_0 0x2b0
886 +#define ISP_REG_AWB_Y2_CFG_1 0x2b4
887 +#define ISP_REG_AWB_Y3_CFG_0 0x2b8
888 +#define ISP_REG_AWB_Y3_CFG_1 0x2bc
889 +#define AWB_Y_SYMBOL_H(n) ((n) << 16)
890 +#define AWB_Y_SYMBOL_L(n) ((n) << 0)
891 +
892 +#define ISP_REG_AWB_S0_CFG_0 0x2c0
893 +#define ISP_REG_AWB_S0_CFG_1 0x2c4
894 +#define ISP_REG_AWB_S1_CFG_0 0x2c8
895 +#define ISP_REG_AWB_S1_CFG_1 0x2cc
896 +#define ISP_REG_AWB_S2_CFG_0 0x2d0
897 +#define ISP_REG_AWB_S2_CFG_1 0x2d4
898 +#define ISP_REG_AWB_S3_CFG_0 0x2d8
899 +#define ISP_REG_AWB_S3_CFG_1 0x2dc
900 +#define AWB_S_SYMBOL_H(n) ((n) << 16)
901 +#define AWB_S_SYMBOL_L(n) ((n) << 0)
902 +
903 +#define ISP_REG_OBCG_CFG_0 0x2e0
904 +#define ISP_REG_OBCG_CFG_1 0x2e4
905 +#define ISP_REG_OBCG_CFG_2 0x2e8
906 +#define ISP_REG_OBCG_CFG_3 0x2ec
907 +#define ISP_REG_OBCO_CFG_0 0x2f0
908 +#define ISP_REG_OBCO_CFG_1 0x2f4
909 +#define ISP_REG_OBCO_CFG_2 0x2f8
910 +#define ISP_REG_OBCO_CFG_3 0x2fc
911 +#define GAIN_D_POINT(x) ((x) << 24)
912 +#define GAIN_C_POINT(x) ((x) << 16)
913 +#define GAIN_B_POINT(x) ((x) << 8)
914 +#define GAIN_A_POINT(x) ((x) << 0)
915 +#define OFFSET_D_POINT(x) ((x) << 24)
916 +#define OFFSET_C_POINT(x) ((x) << 16)
917 +#define OFFSET_B_POINT(x) ((x) << 8)
918 +#define OFFSET_A_POINT(x) ((x) << 0)
919 +
920 +#define ISP_REG_ISP_CTRL_0 0xa00
921 +#define ISPC_SCFEINT BIT(27)
922 +#define ISPC_VSFWINT BIT(26)
923 +#define ISPC_VSINT BIT(25)
924 +#define ISPC_INTS BIT(24)
925 +#define ISPC_ENUO BIT(20)
926 +#define ISPC_ENLS BIT(17)
927 +#define ISPC_ENSS1 BIT(12)
928 +#define ISPC_ENSS0 BIT(11)
929 +#define ISPC_RST BIT(1)
930 +#define ISPC_EN BIT(0)
931 +#define ISPC_RST_MASK BIT(1)
932 +
933 +#define ISP_REG_ISP_CTRL_1 0xa08
934 +#define CTRL_SAT(n) ((n) << 28)
935 +#define CTRL_DBC BIT(22)
936 +#define CTRL_CTC BIT(21)
937 +#define CTRL_YHIST BIT(20)
938 +#define CTRL_YCURVE BIT(19)
939 +#define CTRL_CTM BIT(18)
940 +#define CTRL_BIYUV BIT(17)
941 +#define CTRL_SCE BIT(8)
942 +#define CTRL_EE BIT(7)
943 +#define CTRL_CCE BIT(5)
944 +#define CTRL_RGE BIT(4)
945 +#define CTRL_CME BIT(3)
946 +#define CTRL_AE BIT(2)
947 +#define CTRL_CE BIT(1)
948 +#define CTRL_SAT_MASK GENMASK(31, 28)
949 +
950 +#define ISP_REG_PIPELINE_XY_SIZE 0xa0c
951 +#define H_ACT_CAP(n) ((n) << 16)
952 +#define W_ACT_CAP(n) ((n) << 0)
953 +
954 +#define ISP_REG_ICTC 0xa10
955 +#define GF_MODE(n) ((n) << 30)
956 +#define MAXGT(n) ((n) << 16)
957 +#define MINGT(n) ((n) << 0)
958 +
959 +#define ISP_REG_IDBC 0xa14
960 +#define BADGT(n) ((n) << 16)
961 +#define BADXT(n) ((n) << 0)
962 +
963 +#define ISP_REG_ICFAM 0xa1c
964 +#define CROSS_COV(n) ((n) << 4)
965 +#define HV_W(n) ((n) << 0)
966 +
967 +#define ISP_REG_CS_GAIN 0xa30
968 +#define CMAD(n) ((n) << 16)
969 +#define CMAB(n) ((n) << 0)
970 +
971 +#define ISP_REG_CS_THRESHOLD 0xa34
972 +#define CMD(n) ((n) << 16)
973 +#define CMB(n) ((n) << 0)
974 +
975 +#define ISP_REG_CS_OFFSET 0xa38
976 +#define VOFF(n) ((n) << 16)
977 +#define UOFF(n) ((n) << 0)
978 +
979 +#define ISP_REG_CS_HUE_F 0xa3c
980 +#define SIN(n) ((n) << 16)
981 +#define COS(n) ((n) << 0)
982 +
983 +#define ISP_REG_CS_SCALE 0xa40
984 +#define CMSF(n) ((n) << 0)
985 +
986 +#define ISP_REG_IESHD 0xa50
987 +#define SHAD_UP_M BIT(1)
988 +#define SHAD_UP_EN BIT(0)
989 +
990 +#define ISP_REG_YADJ0 0xa54
991 +#define YOIR(n) ((n) << 16)
992 +#define YIMIN(n) ((n) << 0)
993 +
994 +#define ISP_REG_YADJ1 0xa58
995 +#define YOMAX(n) ((n) << 16)
996 +#define YOMIN(n) ((n) << 0)
997 +
998 +#define ISP_REG_Y_PLANE_START_ADDR 0xa80
999 +#define ISP_REG_UV_PLANE_START_ADDR 0xa84
1000 +
1001 +#define ISP_REG_STRIDE 0xa88
1002 +#define IMG_STR(n) ((n) << 0)
1003 +
1004 +#define ISP_REG_ITIIWSR 0xb20
1005 +#define ITI_HSIZE(n) ((n) << 16)
1006 +#define ITI_WSIZE(n) ((n) << 0)
1007 +
1008 +#define ISP_REG_ITIDWLSR 0xb24
1009 +#define ITI_WSTRIDE(n) ((n) << 0)
1010 +
1011 +#define ISP_REG_ITIPDFR 0xb38
1012 +#define ITI_PACKAGE_FMT(n) ((n) << 0)
1013 +
1014 +#define ISP_REG_ITIDRLSR 0xb3C
1015 +#define ITI_STRIDE_L(n) ((n) << 0)
1016 +
1017 +#define ISP_REG_DNYUV_YSWR0 0xc00
1018 +#define ISP_REG_DNYUV_YSWR1 0xc04
1019 +#define ISP_REG_DNYUV_CSWR0 0xc08
1020 +#define ISP_REG_DNYUV_CSWR1 0xc0c
1021 +#define YUVSW5(n) ((n) << 20)
1022 +#define YUVSW4(n) ((n) << 16)
1023 +#define YUVSW3(n) ((n) << 12)
1024 +#define YUVSW2(n) ((n) << 8)
1025 +#define YUVSW1(n) ((n) << 4)
1026 +#define YUVSW0(n) ((n) << 0)
1027 +
1028 +#define ISP_REG_DNYUV_YDR0 0xc10
1029 +#define ISP_REG_DNYUV_YDR1 0xc14
1030 +#define ISP_REG_DNYUV_YDR2 0xc18
1031 +#define ISP_REG_DNYUV_CDR0 0xc1c
1032 +#define ISP_REG_DNYUV_CDR1 0xc20
1033 +#define ISP_REG_DNYUV_CDR2 0xc24
1034 +#define CURVE_D_H(n) ((n) << 16)
1035 +#define CURVE_D_L(n) ((n) << 0)
1036 +
1037 +#define ISP_REG_ICAMD_0 0xc40
1038 +#define DNRM_F(n) ((n) << 16)
1039 +#define ISP_REG_ICAMD_12 0xc70
1040 +#define ISP_REG_ICAMD_20 0xc90
1041 +#define ISP_REG_ICAMD_24 0xca0
1042 +#define ISP_REG_ICAMD_25 0xca4
1043 +#define CCM_M_DAT(n) ((n) << 0)
1044 +
1045 +#define ISP_REG_GAMMA_VAL0 0xe00
1046 +#define ISP_REG_GAMMA_VAL1 0xe04
1047 +#define ISP_REG_GAMMA_VAL2 0xe08
1048 +#define ISP_REG_GAMMA_VAL3 0xe0c
1049 +#define ISP_REG_GAMMA_VAL4 0xe10
1050 +#define ISP_REG_GAMMA_VAL5 0xe14
1051 +#define ISP_REG_GAMMA_VAL6 0xe18
1052 +#define ISP_REG_GAMMA_VAL7 0xe1c
1053 +#define ISP_REG_GAMMA_VAL8 0xe20
1054 +#define ISP_REG_GAMMA_VAL9 0xe24
1055 +#define ISP_REG_GAMMA_VAL10 0xe28
1056 +#define ISP_REG_GAMMA_VAL11 0xe2c
1057 +#define ISP_REG_GAMMA_VAL12 0xe30
1058 +#define ISP_REG_GAMMA_VAL13 0xe34
1059 +#define ISP_REG_GAMMA_VAL14 0xe38
1060 +#define GAMMA_S_VAL(n) ((n) << 16)
1061 +#define GAMMA_VAL(n) ((n) << 0)
1062 +
1063 +#define ISP_REG_R2Y_0 0xe40
1064 +#define ISP_REG_R2Y_1 0xe44
1065 +#define ISP_REG_R2Y_2 0xe48
1066 +#define ISP_REG_R2Y_3 0xe4c
1067 +#define ISP_REG_R2Y_4 0xe50
1068 +#define ISP_REG_R2Y_5 0xe54
1069 +#define ISP_REG_R2Y_6 0xe58
1070 +#define ISP_REG_R2Y_7 0xe5c
1071 +#define ISP_REG_R2Y_8 0xe60
1072 +#define CSC_M(n) ((n) << 0)
1073 +
1074 +#define ISP_REG_SHARPEN0 0xe80
1075 +#define ISP_REG_SHARPEN1 0xe84
1076 +#define ISP_REG_SHARPEN2 0xe88
1077 +#define ISP_REG_SHARPEN3 0xe8c
1078 +#define ISP_REG_SHARPEN4 0xe90
1079 +#define ISP_REG_SHARPEN5 0xe94
1080 +#define ISP_REG_SHARPEN6 0xe98
1081 +#define ISP_REG_SHARPEN7 0xe9c
1082 +#define ISP_REG_SHARPEN8 0xea0
1083 +#define ISP_REG_SHARPEN9 0xea4
1084 +#define ISP_REG_SHARPEN10 0xea8
1085 +#define ISP_REG_SHARPEN11 0xeac
1086 +#define ISP_REG_SHARPEN12 0xeb0
1087 +#define ISP_REG_SHARPEN13 0xeb4
1088 +#define ISP_REG_SHARPEN14 0xeb8
1089 +#define S_DELTA(n) ((n) << 16)
1090 +#define S_WEIGHT(n) ((n) << 8)
1091 +
1092 +#define ISP_REG_SHARPEN_FS0 0xebc
1093 +#define ISP_REG_SHARPEN_FS1 0xec0
1094 +#define ISP_REG_SHARPEN_FS2 0xec4
1095 +#define ISP_REG_SHARPEN_FS3 0xec8
1096 +#define ISP_REG_SHARPEN_FS4 0xecc
1097 +#define ISP_REG_SHARPEN_FS5 0xed0
1098 +#define S_FACTOR(n) ((n) << 24)
1099 +#define S_SLOPE(n) ((n) << 0)
1100 +
1101 +#define ISP_REG_SHARPEN_WN 0xed4
1102 +#define PDIRF(n) ((n) << 28)
1103 +#define NDIRF(n) ((n) << 24)
1104 +#define WSUM(n) ((n) << 0)
1105 +
1106 +#define ISP_REG_IUVS1 0xed8
1107 +#define UVDIFF2(n) ((n) << 16)
1108 +#define UVDIFF1(n) ((n) << 0)
1109 +
1110 +#define ISP_REG_IUVS2 0xedc
1111 +#define UVF(n) ((n) << 24)
1112 +#define UVSLOPE(n) ((n) << 0)
1113 +
1114 +#define ISP_REG_IUVCKS1 0xee0
1115 +#define UVCKDIFF2(n) ((n) << 16)
1116 +#define UVCKDIFF1(n) ((n) << 0)
1117 +
1118 +#define ISP_REG_IUVCKS2 0xee4
1119 +#define UVCKSLOPE(n) ((n) << 0)
1120 +
1121 +#define ISP_REG_ISHRPET 0xee8
1122 +#define TH(n) ((n) << 8)
1123 +#define EN(n) ((n) << 0)
1124 +
1125 +#define ISP_REG_YCURVE_0 0xf00
1126 +#define ISP_REG_YCURVE_63 0xffc
1127 +#define L_PARAM(n) ((n) << 0)
1128 +
1129 +#define IMAGE_MAX_WIDTH 1920
1130 +#define IMAGE_MAX_HEIGH 1080
1131 +
1132 +/* The output line of ISP */
1133 +enum isp_line_id {
1134 + STF_ISP_LINE_INVALID = -1,
1135 + STF_ISP_LINE_SRC = 1,
1136 + STF_ISP_LINE_MAX = STF_ISP_LINE_SRC
1137 +};
1138 +
1139 +/* pad id for media framework */
1140 +enum isp_pad_id {
1141 + STF_ISP_PAD_SINK = 0,
1142 + STF_ISP_PAD_SRC,
1143 + STF_ISP_PAD_MAX
1144 +};
1145 +
1146 +enum {
1147 + EN_INT_NONE = 0,
1148 + EN_INT_ISP_DONE = (0x1 << 24),
1149 + EN_INT_CSI_DONE = (0x1 << 25),
1150 + EN_INT_SC_DONE = (0x1 << 26),
1151 + EN_INT_LINE_INT = (0x1 << 27),
1152 + EN_INT_ALL = (0xF << 24),
1153 +};
1154 +
1155 +enum {
1156 + INTERFACE_DVP = 0,
1157 + INTERFACE_CSI,
1158 +};
1159 +
1160 +struct isp_format {
1161 + u32 code;
1162 + u8 bpp;
1163 +};
1164 +
1165 +struct isp_format_table {
1166 + const struct isp_format *fmts;
1167 + int nfmts;
1168 +};
1169 +
1170 +struct regval_t {
1171 + u32 addr;
1172 + u32 val;
1173 + u32 delay_ms;
1174 +};
1175 +
1176 +struct reg_table {
1177 + const struct regval_t *regval;
1178 + int regval_num;
1179 +};
1180 +
1181 +struct stf_isp_crop {
1182 + struct v4l2_rect rect;
1183 + u32 bpp;
1184 +};
1185 +
1186 +struct stf_isp_dev {
1187 + enum stf_subdev_type sdev_type; /* This member must be first */
1188 + struct stfcamss *stfcamss;
1189 + struct v4l2_subdev subdev;
1190 + struct media_pad pads[STF_ISP_PAD_MAX];
1191 + struct v4l2_mbus_framefmt fmt[STF_ISP_PAD_MAX];
1192 + struct stf_isp_crop rect[STF_ISP_PAD_MAX];
1193 + const struct isp_format_table *formats;
1194 + unsigned int nformats;
1195 + struct mutex power_lock; /* serialize power control*/
1196 + int power_count;
1197 + struct mutex stream_lock; /* serialize stream control */
1198 + int stream_count;
1199 +};
1200 +
1201 +int stf_isp_clk_enable(struct stf_isp_dev *isp_dev);
1202 +int stf_isp_clk_disable(struct stf_isp_dev *isp_dev);
1203 +int stf_isp_reset(struct stf_isp_dev *isp_dev);
1204 +void stf_isp_init_cfg(struct stf_isp_dev *isp_dev);
1205 +void stf_isp_settings(struct stf_isp_dev *isp_dev,
1206 + struct stf_isp_crop *crop_array, u32 mcode);
1207 +void stf_isp_stream_set(struct stf_isp_dev *isp_dev);
1208 +int stf_isp_subdev_init(struct stfcamss *stfcamss);
1209 +int stf_isp_register(struct stf_isp_dev *isp_dev, struct v4l2_device *v4l2_dev);
1210 +int stf_isp_unregister(struct stf_isp_dev *isp_dev);
1211 +
1212 +#endif /* STF_ISP_H */
1213 --- /dev/null
1214 +++ b/drivers/media/platform/starfive/stf_isp_hw_ops.c
1215 @@ -0,0 +1,452 @@
1216 +// SPDX-License-Identifier: GPL-2.0
1217 +/*
1218 + * stf_isp_hw_ops.c
1219 + *
1220 + * Register interface file for StarFive ISP driver
1221 + *
1222 + * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
1223 + *
1224 + */
1225 +
1226 +#include "stf_camss.h"
1227 +
1228 +static void stf_isp_config_obc(struct stfcamss *stfcamss)
1229 +{
1230 + u32 reg_val, reg_add;
1231 +
1232 + stf_isp_reg_write(stfcamss, ISP_REG_OBC_CFG, OBC_W_H(11) | OBC_W_W(11));
1233 +
1234 + reg_val = GAIN_D_POINT(0x40) | GAIN_C_POINT(0x40) |
1235 + GAIN_B_POINT(0x40) | GAIN_A_POINT(0x40);
1236 + for (reg_add = ISP_REG_OBCG_CFG_0; reg_add <= ISP_REG_OBCG_CFG_3;) {
1237 + stf_isp_reg_write(stfcamss, reg_add, reg_val);
1238 + reg_add += 4;
1239 + }
1240 +
1241 + reg_val = OFFSET_D_POINT(0) | OFFSET_C_POINT(0) |
1242 + OFFSET_B_POINT(0) | OFFSET_A_POINT(0);
1243 + for (reg_add = ISP_REG_OBCO_CFG_0; reg_add <= ISP_REG_OBCO_CFG_3;) {
1244 + stf_isp_reg_write(stfcamss, reg_add, reg_val);
1245 + reg_add += 4;
1246 + }
1247 +}
1248 +
1249 +static void stf_isp_config_oecf(struct stfcamss *stfcamss)
1250 +{
1251 + u32 reg_add, par_val;
1252 + u16 par_h, par_l;
1253 +
1254 + par_h = 0x10; par_l = 0;
1255 + par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
1256 + for (reg_add = ISP_REG_OECF_X0_CFG0; reg_add <= ISP_REG_OECF_Y3_CFG0;) {
1257 + stf_isp_reg_write(stfcamss, reg_add, par_val);
1258 + reg_add += 0x20;
1259 + }
1260 +
1261 + par_h = 0x40; par_l = 0x20;
1262 + par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
1263 + for (reg_add = ISP_REG_OECF_X0_CFG1; reg_add <= ISP_REG_OECF_Y3_CFG1;) {
1264 + stf_isp_reg_write(stfcamss, reg_add, par_val);
1265 + reg_add += 0x20;
1266 + }
1267 +
1268 + par_h = 0x80; par_l = 0x60;
1269 + par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
1270 + for (reg_add = ISP_REG_OECF_X0_CFG2; reg_add <= ISP_REG_OECF_Y3_CFG2;) {
1271 + stf_isp_reg_write(stfcamss, reg_add, par_val);
1272 + reg_add += 0x20;
1273 + }
1274 +
1275 + par_h = 0xc0; par_l = 0xa0;
1276 + par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
1277 + for (reg_add = ISP_REG_OECF_X0_CFG3; reg_add <= ISP_REG_OECF_Y3_CFG3;) {
1278 + stf_isp_reg_write(stfcamss, reg_add, par_val);
1279 + reg_add += 0x20;
1280 + }
1281 +
1282 + par_h = 0x100; par_l = 0xe0;
1283 + par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
1284 + for (reg_add = ISP_REG_OECF_X0_CFG4; reg_add <= ISP_REG_OECF_Y3_CFG4;) {
1285 + stf_isp_reg_write(stfcamss, reg_add, par_val);
1286 + reg_add += 0x20;
1287 + }
1288 +
1289 + par_h = 0x200; par_l = 0x180;
1290 + par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
1291 + for (reg_add = ISP_REG_OECF_X0_CFG5; reg_add <= ISP_REG_OECF_Y3_CFG5;) {
1292 + stf_isp_reg_write(stfcamss, reg_add, par_val);
1293 + reg_add += 0x20;
1294 + }
1295 +
1296 + par_h = 0x300; par_l = 0x280;
1297 + par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
1298 + for (reg_add = ISP_REG_OECF_X0_CFG6; reg_add <= ISP_REG_OECF_Y3_CFG6;) {
1299 + stf_isp_reg_write(stfcamss, reg_add, par_val);
1300 + reg_add += 0x20;
1301 + }
1302 +
1303 + par_h = 0x3fe; par_l = 0x380;
1304 + par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
1305 + for (reg_add = ISP_REG_OECF_X0_CFG7; reg_add <= ISP_REG_OECF_Y3_CFG7;) {
1306 + stf_isp_reg_write(stfcamss, reg_add, par_val);
1307 + reg_add += 0x20;
1308 + }
1309 +
1310 + par_h = 0x80; par_l = 0x80;
1311 + par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
1312 + for (reg_add = ISP_REG_OECF_S0_CFG0; reg_add <= ISP_REG_OECF_S3_CFG7;) {
1313 + stf_isp_reg_write(stfcamss, reg_add, par_val);
1314 + reg_add += 4;
1315 + }
1316 +}
1317 +
1318 +static void stf_isp_config_awb(struct stfcamss *stfcamss)
1319 +{
1320 + u32 reg_val, reg_add;
1321 + u16 symbol_h, symbol_l;
1322 +
1323 + symbol_h = 0x0; symbol_l = 0x0;
1324 + reg_val = AWB_X_SYMBOL_H(symbol_h) | AWB_X_SYMBOL_L(symbol_l);
1325 +
1326 + for (reg_add = ISP_REG_AWB_X0_CFG_0; reg_add <= ISP_REG_AWB_X3_CFG_1;) {
1327 + stf_isp_reg_write(stfcamss, reg_add, reg_val);
1328 + reg_add += 4;
1329 + }
1330 +
1331 + symbol_h = 0x0, symbol_l = 0x0;
1332 + reg_val = AWB_Y_SYMBOL_H(symbol_h) | AWB_Y_SYMBOL_L(symbol_l);
1333 +
1334 + for (reg_add = ISP_REG_AWB_Y0_CFG_0; reg_add <= ISP_REG_AWB_Y3_CFG_1;) {
1335 + stf_isp_reg_write(stfcamss, reg_add, reg_val);
1336 + reg_add += 4;
1337 + }
1338 +
1339 + symbol_h = 0x80, symbol_l = 0x80;
1340 + reg_val = AWB_S_SYMBOL_H(symbol_h) | AWB_S_SYMBOL_L(symbol_l);
1341 +
1342 + for (reg_add = ISP_REG_AWB_S0_CFG_0; reg_add <= ISP_REG_AWB_S3_CFG_1;) {
1343 + stf_isp_reg_write(stfcamss, reg_add, reg_val);
1344 + reg_add += 4;
1345 + }
1346 +}
1347 +
1348 +static void stf_isp_config_grgb(struct stfcamss *stfcamss)
1349 +{
1350 + stf_isp_reg_write(stfcamss, ISP_REG_ICTC,
1351 + GF_MODE(1) | MAXGT(0x140) | MINGT(0x40));
1352 + stf_isp_reg_write(stfcamss, ISP_REG_IDBC, BADGT(0x200) | BADXT(0x200));
1353 +}
1354 +
1355 +static void stf_isp_config_cfa(struct stfcamss *stfcamss)
1356 +{
1357 + stf_isp_reg_write(stfcamss, ISP_REG_RAW_FORMAT_CFG,
1358 + SMY13(0) | SMY12(1) | SMY11(0) | SMY10(1) | SMY3(2) |
1359 + SMY2(3) | SMY1(2) | SMY0(3));
1360 + stf_isp_reg_write(stfcamss, ISP_REG_ICFAM, CROSS_COV(3) | HV_W(2));
1361 +}
1362 +
1363 +static void stf_isp_config_ccm(struct stfcamss *stfcamss)
1364 +{
1365 + u32 reg_add;
1366 +
1367 + stf_isp_reg_write(stfcamss, ISP_REG_ICAMD_0, DNRM_F(6) | CCM_M_DAT(0));
1368 +
1369 + for (reg_add = ISP_REG_ICAMD_12; reg_add <= ISP_REG_ICAMD_20;) {
1370 + stf_isp_reg_write(stfcamss, reg_add, CCM_M_DAT(0x80));
1371 + reg_add += 0x10;
1372 + }
1373 +
1374 + stf_isp_reg_write(stfcamss, ISP_REG_ICAMD_24, CCM_M_DAT(0x700));
1375 + stf_isp_reg_write(stfcamss, ISP_REG_ICAMD_25, CCM_M_DAT(0x200));
1376 +}
1377 +
1378 +static void stf_isp_config_gamma(struct stfcamss *stfcamss)
1379 +{
1380 + u32 reg_val, reg_add;
1381 + u16 gamma_slope_v, gamma_v;
1382 +
1383 + gamma_slope_v = 0x2400; gamma_v = 0x0;
1384 + reg_val = GAMMA_S_VAL(gamma_slope_v) | GAMMA_VAL(gamma_v);
1385 + stf_isp_reg_write(stfcamss, ISP_REG_GAMMA_VAL0, reg_val);
1386 +
1387 + gamma_slope_v = 0x800; gamma_v = 0x20;
1388 + for (reg_add = ISP_REG_GAMMA_VAL1; reg_add <= ISP_REG_GAMMA_VAL7;) {
1389 + reg_val = GAMMA_S_VAL(gamma_slope_v) | GAMMA_VAL(gamma_v);
1390 + stf_isp_reg_write(stfcamss, reg_add, reg_val);
1391 + reg_add += 4;
1392 + gamma_v += 0x20;
1393 + }
1394 +
1395 + gamma_v = 0x100;
1396 + for (reg_add = ISP_REG_GAMMA_VAL8; reg_add <= ISP_REG_GAMMA_VAL13;) {
1397 + reg_val = GAMMA_S_VAL(gamma_slope_v) | GAMMA_VAL(gamma_v);
1398 + stf_isp_reg_write(stfcamss, reg_add, reg_val);
1399 + reg_add += 4;
1400 + gamma_v += 0x80;
1401 + }
1402 +
1403 + gamma_v = 0x3fe;
1404 + reg_val = GAMMA_S_VAL(gamma_slope_v) | GAMMA_VAL(gamma_v);
1405 + stf_isp_reg_write(stfcamss, ISP_REG_GAMMA_VAL14, reg_val);
1406 +}
1407 +
1408 +static void stf_isp_config_r2y(struct stfcamss *stfcamss)
1409 +{
1410 + stf_isp_reg_write(stfcamss, ISP_REG_R2Y_0, CSC_M(0x4C));
1411 + stf_isp_reg_write(stfcamss, ISP_REG_R2Y_1, CSC_M(0x97));
1412 + stf_isp_reg_write(stfcamss, ISP_REG_R2Y_2, CSC_M(0x1d));
1413 + stf_isp_reg_write(stfcamss, ISP_REG_R2Y_3, CSC_M(0x1d5));
1414 + stf_isp_reg_write(stfcamss, ISP_REG_R2Y_4, CSC_M(0x1ac));
1415 + stf_isp_reg_write(stfcamss, ISP_REG_R2Y_5, CSC_M(0x80));
1416 + stf_isp_reg_write(stfcamss, ISP_REG_R2Y_6, CSC_M(0x80));
1417 + stf_isp_reg_write(stfcamss, ISP_REG_R2Y_7, CSC_M(0x194));
1418 + stf_isp_reg_write(stfcamss, ISP_REG_R2Y_8, CSC_M(0x1ec));
1419 +}
1420 +
1421 +static void stf_isp_config_y_curve(struct stfcamss *stfcamss)
1422 +{
1423 + u32 reg_add;
1424 + u16 y_curve;
1425 +
1426 + y_curve = 0x0;
1427 + for (reg_add = ISP_REG_YCURVE_0; reg_add <= ISP_REG_YCURVE_63;) {
1428 + stf_isp_reg_write(stfcamss, reg_add, y_curve);
1429 + reg_add += 4;
1430 + y_curve += 0x10;
1431 + }
1432 +}
1433 +
1434 +static void stf_isp_config_sharpen(struct stfcamss *sc)
1435 +{
1436 + u32 reg_add;
1437 +
1438 + stf_isp_reg_write(sc, ISP_REG_SHARPEN0, S_DELTA(0x7) | S_WEIGHT(0xf));
1439 + stf_isp_reg_write(sc, ISP_REG_SHARPEN1, S_DELTA(0x18) | S_WEIGHT(0xf));
1440 + stf_isp_reg_write(sc, ISP_REG_SHARPEN2, S_DELTA(0x80) | S_WEIGHT(0xf));
1441 + stf_isp_reg_write(sc, ISP_REG_SHARPEN3, S_DELTA(0x100) | S_WEIGHT(0xf));
1442 + stf_isp_reg_write(sc, ISP_REG_SHARPEN4, S_DELTA(0x10) | S_WEIGHT(0xf));
1443 + stf_isp_reg_write(sc, ISP_REG_SHARPEN5, S_DELTA(0x60) | S_WEIGHT(0xf));
1444 + stf_isp_reg_write(sc, ISP_REG_SHARPEN6, S_DELTA(0x100) | S_WEIGHT(0xf));
1445 + stf_isp_reg_write(sc, ISP_REG_SHARPEN7, S_DELTA(0x190) | S_WEIGHT(0xf));
1446 + stf_isp_reg_write(sc, ISP_REG_SHARPEN8, S_DELTA(0x0) | S_WEIGHT(0xf));
1447 +
1448 + for (reg_add = ISP_REG_SHARPEN9; reg_add <= ISP_REG_SHARPEN14;) {
1449 + stf_isp_reg_write(sc, reg_add, S_WEIGHT(0xf));
1450 + reg_add += 4;
1451 + }
1452 +
1453 + for (reg_add = ISP_REG_SHARPEN_FS0; reg_add <= ISP_REG_SHARPEN_FS5;) {
1454 + stf_isp_reg_write(sc, reg_add, S_FACTOR(0x10) | S_SLOPE(0x0));
1455 + reg_add += 4;
1456 + }
1457 +
1458 + stf_isp_reg_write(sc, ISP_REG_SHARPEN_WN,
1459 + PDIRF(0x8) | NDIRF(0x8) | WSUM(0xd7c));
1460 + stf_isp_reg_write(sc, ISP_REG_IUVS1, UVDIFF2(0xC0) | UVDIFF1(0x40));
1461 + stf_isp_reg_write(sc, ISP_REG_IUVS2, UVF(0xff) | UVSLOPE(0x0));
1462 + stf_isp_reg_write(sc, ISP_REG_IUVCKS1,
1463 + UVCKDIFF2(0xa0) | UVCKDIFF1(0x40));
1464 +}
1465 +
1466 +static void stf_isp_config_dnyuv(struct stfcamss *stfcamss)
1467 +{
1468 + u32 reg_val;
1469 +
1470 + reg_val = YUVSW5(7) | YUVSW4(7) | YUVSW3(7) | YUVSW2(7) |
1471 + YUVSW1(7) | YUVSW0(7);
1472 + stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_YSWR0, reg_val);
1473 + stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_CSWR0, reg_val);
1474 +
1475 + reg_val = YUVSW3(7) | YUVSW2(7) | YUVSW1(7) | YUVSW0(7);
1476 + stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_YSWR1, reg_val);
1477 + stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_CSWR1, reg_val);
1478 +
1479 + reg_val = CURVE_D_H(0x60) | CURVE_D_L(0x40);
1480 + stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_YDR0, reg_val);
1481 + stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_CDR0, reg_val);
1482 +
1483 + reg_val = CURVE_D_H(0xd8) | CURVE_D_L(0x90);
1484 + stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_YDR1, reg_val);
1485 + stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_CDR1, reg_val);
1486 +
1487 + reg_val = CURVE_D_H(0x1e6) | CURVE_D_L(0x144);
1488 + stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_YDR2, reg_val);
1489 + stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_CDR2, reg_val);
1490 +}
1491 +
1492 +static void stf_isp_config_sat(struct stfcamss *stfcamss)
1493 +{
1494 + stf_isp_reg_write(stfcamss, ISP_REG_CS_GAIN, CMAD(0x0) | CMAB(0x100));
1495 + stf_isp_reg_write(stfcamss, ISP_REG_CS_THRESHOLD, CMD(0x1f) | CMB(0x1));
1496 + stf_isp_reg_write(stfcamss, ISP_REG_CS_OFFSET, VOFF(0x0) | UOFF(0x0));
1497 + stf_isp_reg_write(stfcamss, ISP_REG_CS_HUE_F, SIN(0x0) | COS(0x100));
1498 + stf_isp_reg_write(stfcamss, ISP_REG_CS_SCALE, CMSF(0x8));
1499 + stf_isp_reg_write(stfcamss, ISP_REG_YADJ0, YOIR(0x401) | YIMIN(0x1));
1500 + stf_isp_reg_write(stfcamss, ISP_REG_YADJ1, YOMAX(0x3ff) | YOMIN(0x1));
1501 +}
1502 +
1503 +int stf_isp_clk_enable(struct stf_isp_dev *isp_dev)
1504 +{
1505 + struct stfcamss *stfcamss = isp_dev->stfcamss;
1506 +
1507 + clk_prepare_enable(stfcamss->sys_clk[STF_CLK_WRAPPER_CLK_C].clk);
1508 + reset_control_deassert(stfcamss->sys_rst[STF_RST_WRAPPER_C].rstc);
1509 + reset_control_deassert(stfcamss->sys_rst[STF_RST_WRAPPER_P].rstc);
1510 +
1511 + return 0;
1512 +}
1513 +
1514 +int stf_isp_clk_disable(struct stf_isp_dev *isp_dev)
1515 +{
1516 + struct stfcamss *stfcamss = isp_dev->stfcamss;
1517 +
1518 + reset_control_assert(stfcamss->sys_rst[STF_RST_WRAPPER_C].rstc);
1519 + reset_control_assert(stfcamss->sys_rst[STF_RST_WRAPPER_P].rstc);
1520 + clk_disable_unprepare(stfcamss->sys_clk[STF_CLK_WRAPPER_CLK_C].clk);
1521 +
1522 + return 0;
1523 +}
1524 +
1525 +int stf_isp_reset(struct stf_isp_dev *isp_dev)
1526 +{
1527 + stf_isp_reg_set_bit(isp_dev->stfcamss, ISP_REG_ISP_CTRL_0,
1528 + ISPC_RST_MASK, ISPC_RST);
1529 + stf_isp_reg_set_bit(isp_dev->stfcamss, ISP_REG_ISP_CTRL_0,
1530 + ISPC_RST_MASK, 0);
1531 +
1532 + return 0;
1533 +}
1534 +
1535 +void stf_isp_init_cfg(struct stf_isp_dev *isp_dev)
1536 +{
1537 + stf_isp_reg_write(isp_dev->stfcamss, ISP_REG_DC_CFG_1, DC_AXI_ID(0x0));
1538 + stf_isp_reg_write(isp_dev->stfcamss, ISP_REG_DEC_CFG,
1539 + DEC_V_KEEP(0x0) |
1540 + DEC_V_PERIOD(0x0) |
1541 + DEC_H_KEEP(0x0) |
1542 + DEC_H_PERIOD(0x0));
1543 +
1544 + stf_isp_config_obc(isp_dev->stfcamss);
1545 + stf_isp_config_oecf(isp_dev->stfcamss);
1546 + stf_isp_config_awb(isp_dev->stfcamss);
1547 + stf_isp_config_grgb(isp_dev->stfcamss);
1548 + stf_isp_config_cfa(isp_dev->stfcamss);
1549 + stf_isp_config_ccm(isp_dev->stfcamss);
1550 + stf_isp_config_gamma(isp_dev->stfcamss);
1551 + stf_isp_config_r2y(isp_dev->stfcamss);
1552 + stf_isp_config_y_curve(isp_dev->stfcamss);
1553 + stf_isp_config_sharpen(isp_dev->stfcamss);
1554 + stf_isp_config_dnyuv(isp_dev->stfcamss);
1555 + stf_isp_config_sat(isp_dev->stfcamss);
1556 +
1557 + stf_isp_reg_write(isp_dev->stfcamss, ISP_REG_CSI_MODULE_CFG,
1558 + CSI_DUMP_EN | CSI_SC_EN | CSI_AWB_EN |
1559 + CSI_LCCF_EN | CSI_OECF_EN | CSI_OBC_EN | CSI_DEC_EN);
1560 + stf_isp_reg_write(isp_dev->stfcamss, ISP_REG_ISP_CTRL_1,
1561 + CTRL_SAT(1) | CTRL_DBC | CTRL_CTC | CTRL_YHIST |
1562 + CTRL_YCURVE | CTRL_BIYUV | CTRL_SCE | CTRL_EE |
1563 + CTRL_CCE | CTRL_RGE | CTRL_CME | CTRL_AE | CTRL_CE);
1564 +}
1565 +
1566 +static void stf_isp_config_crop(struct stfcamss *stfcamss,
1567 + struct stf_isp_crop *crop)
1568 +{
1569 + struct v4l2_rect *rect = &crop[STF_ISP_PAD_SRC].rect;
1570 + u32 bpp = crop[STF_ISP_PAD_SRC].bpp;
1571 + u32 val;
1572 +
1573 + val = VSTART_CAP(rect->top) | HSTART_CAP(rect->left);
1574 + stf_isp_reg_write(stfcamss, ISP_REG_PIC_CAPTURE_START_CFG, val);
1575 +
1576 + val = VEND_CAP(rect->height + rect->top - 1) |
1577 + HEND_CAP(rect->width + rect->left - 1);
1578 + stf_isp_reg_write(stfcamss, ISP_REG_PIC_CAPTURE_END_CFG, val);
1579 +
1580 + val = H_ACT_CAP(rect->height) | W_ACT_CAP(rect->width);
1581 + stf_isp_reg_write(stfcamss, ISP_REG_PIPELINE_XY_SIZE, val);
1582 +
1583 + val = ALIGN(rect->width * bpp / 8, STFCAMSS_FRAME_WIDTH_ALIGN_8);
1584 + stf_isp_reg_write(stfcamss, ISP_REG_STRIDE, val);
1585 +}
1586 +
1587 +static void stf_isp_config_raw_fmt(struct stfcamss *stfcamss, u32 mcode)
1588 +{
1589 + u32 val, val1;
1590 +
1591 + switch (mcode) {
1592 + case MEDIA_BUS_FMT_SRGGB10_1X10:
1593 + case MEDIA_BUS_FMT_SRGGB8_1X8:
1594 + /* 3 2 3 2 1 0 1 0 B Gb B Gb Gr R Gr R */
1595 + val = SMY13(3) | SMY12(2) | SMY11(3) | SMY10(2) |
1596 + SMY3(1) | SMY2(0) | SMY1(1) | SMY0(0);
1597 + val1 = CTRL_SAT(0x0);
1598 + break;
1599 + case MEDIA_BUS_FMT_SGRBG10_1X10:
1600 + case MEDIA_BUS_FMT_SGRBG8_1X8:
1601 + /* 2 3 2 3 0 1 0 1, Gb B Gb B R Gr R Gr */
1602 + val = SMY13(2) | SMY12(3) | SMY11(2) | SMY10(3) |
1603 + SMY3(0) | SMY2(1) | SMY1(0) | SMY0(1);
1604 + val1 = CTRL_SAT(0x2);
1605 + break;
1606 + case MEDIA_BUS_FMT_SGBRG10_1X10:
1607 + case MEDIA_BUS_FMT_SGBRG8_1X8:
1608 + /* 1 0 1 0 3 2 3 2, Gr R Gr R B Gb B Gb */
1609 + val = SMY13(1) | SMY12(0) | SMY11(1) | SMY10(0) |
1610 + SMY3(3) | SMY2(2) | SMY1(3) | SMY0(2);
1611 + val1 = CTRL_SAT(0x3);
1612 + break;
1613 + case MEDIA_BUS_FMT_SBGGR10_1X10:
1614 + case MEDIA_BUS_FMT_SBGGR8_1X8:
1615 + /* 0 1 0 1 2 3 2 3 R Gr R Gr Gb B Gb B */
1616 + val = SMY13(0) | SMY12(1) | SMY11(0) | SMY10(1) |
1617 + SMY3(2) | SMY2(3) | SMY1(2) | SMY0(3);
1618 + val1 = CTRL_SAT(0x1);
1619 + break;
1620 + default:
1621 + val = SMY13(0) | SMY12(1) | SMY11(0) | SMY10(1) |
1622 + SMY3(2) | SMY2(3) | SMY1(2) | SMY0(3);
1623 + val1 = CTRL_SAT(0x1);
1624 + break;
1625 + }
1626 + stf_isp_reg_write(stfcamss, ISP_REG_RAW_FORMAT_CFG, val);
1627 + stf_isp_reg_set_bit(stfcamss, ISP_REG_ISP_CTRL_1, CTRL_SAT_MASK, val1);
1628 +}
1629 +
1630 +void stf_isp_settings(struct stf_isp_dev *isp_dev,
1631 + struct stf_isp_crop *crop, u32 mcode)
1632 +{
1633 + struct stfcamss *stfcamss = isp_dev->stfcamss;
1634 +
1635 + stf_isp_config_crop(stfcamss, crop);
1636 + stf_isp_config_raw_fmt(stfcamss, mcode);
1637 +
1638 + stf_isp_reg_set_bit(stfcamss, ISP_REG_DUMP_CFG_1,
1639 + DUMP_BURST_LEN_MASK | DUMP_SD_MASK,
1640 + DUMP_BURST_LEN(3));
1641 +
1642 + stf_isp_reg_write(stfcamss, ISP_REG_ITIIWSR,
1643 + ITI_HSIZE(IMAGE_MAX_HEIGH) |
1644 + ITI_WSIZE(IMAGE_MAX_WIDTH));
1645 + stf_isp_reg_write(stfcamss, ISP_REG_ITIDWLSR, ITI_WSTRIDE(0x960));
1646 + stf_isp_reg_write(stfcamss, ISP_REG_ITIDRLSR, ITI_STRIDE_L(0x960));
1647 + stf_isp_reg_write(stfcamss, ISP_REG_SENSOR, 0x1);
1648 +}
1649 +
1650 +void stf_isp_stream_set(struct stf_isp_dev *isp_dev)
1651 +{
1652 + struct stfcamss *stfcamss = isp_dev->stfcamss;
1653 +
1654 + stf_isp_reg_write_delay(stfcamss, ISP_REG_ISP_CTRL_0,
1655 + ISPC_ENUO | ISPC_ENLS | ISPC_RST, 10);
1656 + stf_isp_reg_write_delay(stfcamss, ISP_REG_ISP_CTRL_0,
1657 + ISPC_ENUO | ISPC_ENLS, 10);
1658 + stf_isp_reg_write(stfcamss, ISP_REG_IESHD, SHAD_UP_M);
1659 + stf_isp_reg_write_delay(stfcamss, ISP_REG_ISP_CTRL_0,
1660 + ISPC_ENUO | ISPC_ENLS | ISPC_EN, 10);
1661 + stf_isp_reg_write_delay(stfcamss, ISP_REG_CSIINTS,
1662 + CSI_INTS(1) | CSI_SHA_M(4), 10);
1663 + stf_isp_reg_write_delay(stfcamss, ISP_REG_CSIINTS,
1664 + CSI_INTS(2) | CSI_SHA_M(4), 10);
1665 + stf_isp_reg_write_delay(stfcamss, ISP_REG_CSI_INPUT_EN_AND_STATUS,
1666 + CSI_EN_S, 10);
1667 +}