0085-media-starfive-Add-ISP-driver.patch 47 KB

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