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