From patchwork Fri Jun 7 13:24:43 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Devarsh Thakkar X-Patchwork-Id: 802501 Received: from fllv0015.ext.ti.com (fllv0015.ext.ti.com [198.47.19.141]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2171B194125; Fri, 7 Jun 2024 13:25:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.47.19.141 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717766706; cv=none; b=jdNOHF5eg4S7A3dZhS4LXIb5WZipTL5zeNy9piiPotZYZ39PEjWLzDNZWe9lLoicG9G7GPU4oBdwaSGeXAaqUydVCFrY2OX+W2zj2KP0ot8+0oJ3PXIVcHLccIsWrJYL/0A785mjcB0jM3CZwPBsPqpOON4+FU5DklsfHvzrCfA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717766706; c=relaxed/simple; bh=XCkeTdmb5UlSYGoXVQyM1mXHb7Pmwzz3LJ95NLN5jaw=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=q8BEEI7a0e3r5jYNYAX1Q5AYW7hiFlFUJRZZVioPheWx9xEdU4OIuQJRX8jxQbEGa5eRP0V/47qmHX2eKI2vmlx1trgtrxOy6Z0DOL4fgV7w7eDWR8PRcH8eLrfj2o+2aKa48LQnhtMFHRnvRD3laTZTa6o5DNBJU3pZAp+P+nU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com; spf=pass smtp.mailfrom=ti.com; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b=qkvwqt6+; arc=none smtp.client-ip=198.47.19.141 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ti.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="qkvwqt6+" Received: from fllv0034.itg.ti.com ([10.64.40.246]) by fllv0015.ext.ti.com (8.15.2/8.15.2) with ESMTP id 457DOiYc087159; Fri, 7 Jun 2024 08:24:44 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1717766684; bh=2HowkdMKmfe/bA4sdX1zRcikYqQHIjGaVwnlm56Dfgs=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=qkvwqt6+pnCujOAF6Wv/4v2m58yk3eER3Z5Jvci3873Kw3bRczkKGhRF6Pp9E9Bv2 Tqx8BNH4xEEF7Lbc1cbgNCqgoxht/F0F5EAlBJdqpPg+LE7rE1NUSfSO/UymEwDFN7 udaGMdwHL5Tn8nY/nDpTlDs5yLFT3ho1tJG/BdN4= Received: from DFLE113.ent.ti.com (dfle113.ent.ti.com [10.64.6.34]) by fllv0034.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 457DOiKf094642 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 7 Jun 2024 08:24:44 -0500 Received: from DFLE106.ent.ti.com (10.64.6.27) by DFLE113.ent.ti.com (10.64.6.34) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.23; Fri, 7 Jun 2024 08:24:44 -0500 Received: from lelvsmtp5.itg.ti.com (10.180.75.250) by DFLE106.ent.ti.com (10.64.6.27) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.23 via Frontend Transport; Fri, 7 Jun 2024 08:24:44 -0500 Received: from localhost (ti.dhcp.ti.com [172.24.227.95] (may be forged)) by lelvsmtp5.itg.ti.com (8.15.2/8.15.2) with ESMTP id 457DOhOi033596; Fri, 7 Jun 2024 08:24:44 -0500 From: Devarsh Thakkar To: , , , , , , , , , CC: , , , , , , , , , , , Subject: [PATCH v13 01/13] media: dt-bindings: Add Imagination E5010 JPEG Encoder Date: Fri, 7 Jun 2024 18:54:43 +0530 Message-ID: <20240607132443.3544826-1-devarsht@ti.com> X-Mailer: git-send-email 2.39.1 In-Reply-To: <20240607131900.3535250-1-devarsht@ti.com> References: <20240607131900.3535250-1-devarsht@ti.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Add dt-bindings for Imagination E5010 JPEG Encoder [1] which is implemented as stateful V4L2 M2M driver. The device supports baseline encoding with two different quantization tables and compression ratio as demanded. Minimum resolution supported is 64x64 and Maximum resolution supported is 8192x8192. Link: https://www.ti.com/lit/pdf/spruj16 [1] (Section 7.6 JPEG Encoder) Co-developed-by: David Huang Signed-off-by: David Huang Signed-off-by: Devarsh Thakkar Reviewed-by: Rob Herring --- V13: Update commit message to use Link: syntax V6->V12: No change V5: - Add Reviewed-By tag V4: - Use ti-specific compatible ti,am62a-jpeg-enc as secondary one - Update commit message and title - Remove clock-names as only single clock V3: - Add vendor specific compatible - Update reg names - Update clocks to 1 - Fix dts example with proper naming V2: No change --- .../bindings/media/img,e5010-jpeg-enc.yaml | 75 +++++++++++++++++++ MAINTAINERS | 5 ++ 2 files changed, 80 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/img,e5010-jpeg-enc.yaml diff --git a/Documentation/devicetree/bindings/media/img,e5010-jpeg-enc.yaml b/Documentation/devicetree/bindings/media/img,e5010-jpeg-enc.yaml new file mode 100644 index 000000000000..085020cb9e61 --- /dev/null +++ b/Documentation/devicetree/bindings/media/img,e5010-jpeg-enc.yaml @@ -0,0 +1,75 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/img,e5010-jpeg-enc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Imagination E5010 JPEG Encoder + +maintainers: + - Devarsh Thakkar + +description: | + The E5010 is a JPEG encoder from Imagination Technologies implemented on + TI's AM62A SoC. It is capable of real time encoding of YUV420 and YUV422 + inputs to JPEG and M-JPEG. It supports baseline JPEG Encoding up to + 8Kx8K resolution. + +properties: + compatible: + oneOf: + - items: + - const: ti,am62a-jpeg-enc + - const: img,e5010-jpeg-enc + - const: img,e5010-jpeg-enc + + reg: + items: + - description: The E5010 core register region + - description: The E5010 mmu register region + + reg-names: + items: + - const: core + - const: mmu + + power-domains: + maxItems: 1 + + resets: + maxItems: 1 + + clocks: + maxItems: 1 + + interrupts: + maxItems: 1 + +required: + - compatible + - reg + - reg-names + - interrupts + - clocks + +additionalProperties: false + +examples: + - | + #include + #include + #include + + soc { + #address-cells = <2>; + #size-cells = <2>; + jpeg-encoder@fd20000 { + compatible = "img,e5010-jpeg-enc"; + reg = <0x00 0xfd20000 0x00 0x100>, + <0x00 0xfd20200 0x00 0x200>; + reg-names = "core", "mmu"; + clocks = <&k3_clks 201 0>; + power-domains = <&k3_pds 201 TI_SCI_PD_EXCLUSIVE>; + interrupts = ; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index bb9f8077b37d..f2dcab7af2d1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10781,6 +10781,11 @@ S: Maintained F: Documentation/devicetree/bindings/auxdisplay/img,ascii-lcd.yaml F: drivers/auxdisplay/img-ascii-lcd.c +IMGTEC JPEG ENCODER DRIVER +M: Devarsh Thakkar +S: Supported +F: Documentation/devicetree/bindings/media/img,e5010-jpeg-enc.yaml + IMGTEC IR DECODER DRIVER S: Orphan F: drivers/media/rc/img-ir/ From patchwork Fri Jun 7 13:28:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Devarsh Thakkar X-Patchwork-Id: 802757 Received: from fllv0015.ext.ti.com (fllv0015.ext.ti.com [198.47.19.141]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5A32A19413D; Fri, 7 Jun 2024 13:28:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.47.19.141 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717766908; cv=none; b=UTWJceCdI79H6E40WzQwyIsE06YXfMAQi/MTSCkGMYNhnk3d1oHgHmr+lJBn+E4nCABkW1SzZJzIbjn2DTkhXJqZO9XQwxkF+vveEau4x6WsC8jx4ha39or6kPtxpAQweNBxfEHsTxyc2714xq3woim2xsN/Wircb7a4bx9R3gU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717766908; c=relaxed/simple; bh=JSF34Y5qFgBb4loa4JP/4CC8ozkHnXuzUToa7hnryEA=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Neb+ZLEvc2C/Fuj9gkzX03L1aCv5A4Ql6ea6YHaXYVW++caxhicMO7KwowDP4cf8ivRTcbsdkUeSAZFx5cXnsWDodAealAHuSmcde0zE6bQxzYbT+r3odbdgYtO6xgrFRN+PjJZNm8gS8B6UtJr3bLRUQBfyxMl2RWQxx/33PXE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com; spf=pass smtp.mailfrom=ti.com; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b=qe6IsHX4; arc=none smtp.client-ip=198.47.19.141 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ti.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="qe6IsHX4" Received: from fllv0034.itg.ti.com ([10.64.40.246]) by fllv0015.ext.ti.com (8.15.2/8.15.2) with ESMTP id 457DS8E7088999; Fri, 7 Jun 2024 08:28:08 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1717766888; bh=Wn30ObkN8nbYSTvQcU6W/OVx349VP910Aq4RpM/QCxI=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=qe6IsHX46xoztam8HvGtiuY6yfWMi5UkwMaJJYSWL0mdiiZwDy6KsRqHWTV2C5G83 qmrdCbR5s9RSMagGaf9GxY9W0pEtOhv2tgEtPD+AX1q/nYgtLClWR6J0/+gDV8LwQM aTT3uQ8Op8b7NnDnTqjwxCfDLWfSHMNj956qXPeQ= Received: from DLEE101.ent.ti.com (dlee101.ent.ti.com [157.170.170.31]) by fllv0034.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 457DS8G6096656 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 7 Jun 2024 08:28:08 -0500 Received: from DLEE113.ent.ti.com (157.170.170.24) by DLEE101.ent.ti.com (157.170.170.31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.23; Fri, 7 Jun 2024 08:28:07 -0500 Received: from lelvsmtp5.itg.ti.com (10.180.75.250) by DLEE113.ent.ti.com (157.170.170.24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.23 via Frontend Transport; Fri, 7 Jun 2024 08:28:07 -0500 Received: from localhost (ti.dhcp.ti.com [172.24.227.95] (may be forged)) by lelvsmtp5.itg.ti.com (8.15.2/8.15.2) with ESMTP id 457DS7eY038560; Fri, 7 Jun 2024 08:28:07 -0500 From: Devarsh Thakkar To: , , , , , , , , , CC: , , , , , , , , , , , , Subject: [PATCH v13 02/13] media: imagination: Add E5010 JPEG Encoder driver Date: Fri, 7 Jun 2024 18:58:06 +0530 Message-ID: <20240607132806.3550564-1-devarsht@ti.com> X-Mailer: git-send-email 2.39.1 In-Reply-To: <20240607131900.3535250-1-devarsht@ti.com> References: <20240607131900.3535250-1-devarsht@ti.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 This adds support for stateful V4L2 M2M based driver for Imagination E5010 JPEG Encoder [1] which supports baseline encoding with two different quantization tables and compression ratio as demanded. Support for both contiguous and non-contiguous YUV420 and YUV422 semiplanar formats is added along with alignment restrictions as required by the hardware. System and runtime PM hooks are added in the driver along with v4l2 crop and selection API support. Minimum resolution supported is 64x64 and Maximum resolution supported is 8192x8192. All v4l2-compliance tests are passing [2] : v4l2-compliance -s -f -a -d /dev/video0 -e /dev/video1 Total for e5010 device /dev/video0: 79, Succeeded: 79, Failed: 0, Warnings: 0 NOTE: video1 here is VIVID test pattern generator Also tests [3] were run manually to verify below driver features: - Runtime Power Management - Multi-instance JPEG Encoding - DMABUF import, export support - NV12, NV21, NV16, NV61 video format support - Compression quality S_CTRL - Cropping support using S_SELECTION Existing V4L2 M2M based JPEG drivers namely s5p-jpeg, imx-jpeg and rcar_jpu were referred while making this. TODO: Add MMU and memory tiling support [1]: AM62A TRM (Section 7.6 is for JPEG Encoder) : Link: https://www.ti.com/lit/pdf/spruj16 [2]: v4l2-compliance test : Link: https://gist.github.com/devarsht/1f039c631ca953a57f405cfce1b69e49 [3]: E5010 JPEG Encoder Manual tests : Performance: Link: https://gist.github.com/devarsht/c40672944fd71c9a53ab55adbfd9e28b Functionality: Link: https://gist.github.com/devarsht/8e88fcaabff016bb2bac83d89c9d23ce Compression Quality: Link: https://gist.github.com/devarsht/cbcc7cd97e8c48ba1486caa2b7884655 Multi Instance: Link: https://gist.github.com/devarsht/22c2fca08cd3441fb40f2c7a4cebc95a Crop support: Link: https://gist.github.com/devarsht/de6f5142f678bb1a5338abfd9f814abd Runtime PM: Link: https://gist.github.com/devarsht/70cd95d4440ddc678489d93885ddd4dd Co-developed-by: David Huang Signed-off-by: David Huang Signed-off-by: Devarsh Thakkar Reviewed-by: Benjamin Gaignard --- V13: - Fix below smatch/sparse related warnings for unused variables and update commit message : + | ^~~~~~~ +drivers/media/platform/imagination/e5010-jpeg-enc.c +drivers/media/platform/imagination/e5010-jpeg-enc.c: warning: variable 'queue' set but not used [-Wunused-but-set-variable] + 1433 | struct e5010_q_data *queue; + | ^~~~~ +date V10->V12 - No change V9: - Remove extra filler header data V8: - No change V7: - Add cropping support, fix S_SELECTION and G_SELECTION ioctls - Fix PM use-case: Re-enable hardware on system resume before resuming the v4l2 m2m jobs - Re-instate Reviewed-by tag as discussed afterwards in mailing list V6: - Fix sparse warnings and maintain uniform usage of dev ptr to avoid future such bugs. No more errors received as shown below : `smatch/smatch_scripts/kchecker drivers/media/platform/imagination/e5010*.c CHECK scripts/mod/empty.c CALL scripts/checksyscalls.sh CHECK arch/arm64/kernel/vdso/vgettimeofday.c CC [M] drivers/media/platform/imagination/e5010-jpeg-enc.o CHECK drivers/media/platform/imagination/e5010-jpeg-enc.c` - Drop Reviewed-by: Benjamin Gaignard as patchset got updated to fix sparse warnings mentinoed at https://lore.kernel.org/all/f59b2d27-dc58-40fb-b899-647feb9d72e4@collabora.com/#t V5: - Sort the #includes alphabetically in e5010-jpeg-enc.c - Update commit message to point to V5 test reports V4: - Fix issue with default params setting - Correct v4l2 error prints - Simplify register write functions with single statement return values - Remove unrequired error checks from get_queue() - Drop explicit device_caps setting as it is already taken care by v4l2 core - Remove unrequired multiplanar checks and memset from s_fmt, g_fmt callback functions - Fix try_fmt callback to not update the queues - Remove unrequired contiguous format attribute from queue_init - Use dynamic allocation for video_device and remove unrequired assignments in probe() - Remove unrequired checks from queue_setup function - Return queued buffers back if start_streaming fails - Use ARRAY_SIZE in place of hard-coding - Use huffman and quantization tables from reference header file V3: - Correct license headers - Use more generic name core instead of jasper for base registers - Add Comment for forward declarations - Simplify quantization table calculations - Use v4l2_apply_frmsize_constraints for updating framesize and remove unrequired functions - Place TODO at top of file and in commit message too - Use dev_err_probe helper in probe function - Fix return value checking for failure scenarios in probe function - Use v4l2_err/info/warn helpers instead of dev_err/info/warn helpers - Fix unexpected indentation - Correct commit message - Remove dependency on ARCH_K3 as driver is not specific to that V2: No change Link to previous patch revisions: V3: https://lore.kernel.org/all/20230816152210.4080779-3-devarsht@ti.com/ V4: https://lore.kernel.org/all/20240205114239.924697-4-devarsht@ti.com/ V5: https://lore.kernel.org/all/20240215134641.3381478-4-devarsht@ti.com/ V6: https://lore.kernel.org/all/20240228141140.3530612-4-devarsht@ti.com/ V7: https://lore.kernel.org/all/20240510083257.1274730-1-devarsht@ti.com/ V8: https://lore.kernel.org/all/20240517172849.781910-1-devarsht@ti.com/ MAINTAINERS | 2 + drivers/media/platform/Kconfig | 1 + drivers/media/platform/Makefile | 1 + drivers/media/platform/imagination/Kconfig | 12 + drivers/media/platform/imagination/Makefile | 3 + .../platform/imagination/e5010-core-regs.h | 585 ++++++ .../platform/imagination/e5010-jpeg-enc-hw.c | 267 +++ .../platform/imagination/e5010-jpeg-enc-hw.h | 42 + .../platform/imagination/e5010-jpeg-enc.c | 1743 +++++++++++++++++ .../platform/imagination/e5010-jpeg-enc.h | 168 ++ .../platform/imagination/e5010-mmu-regs.h | 311 +++ 11 files changed, 3135 insertions(+) create mode 100644 drivers/media/platform/imagination/Kconfig create mode 100644 drivers/media/platform/imagination/Makefile create mode 100644 drivers/media/platform/imagination/e5010-core-regs.h create mode 100644 drivers/media/platform/imagination/e5010-jpeg-enc-hw.c create mode 100644 drivers/media/platform/imagination/e5010-jpeg-enc-hw.h create mode 100644 drivers/media/platform/imagination/e5010-jpeg-enc.c create mode 100644 drivers/media/platform/imagination/e5010-jpeg-enc.h create mode 100644 drivers/media/platform/imagination/e5010-mmu-regs.h diff --git a/MAINTAINERS b/MAINTAINERS index f2dcab7af2d1..be083eb88358 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10783,8 +10783,10 @@ F: drivers/auxdisplay/img-ascii-lcd.c IMGTEC JPEG ENCODER DRIVER M: Devarsh Thakkar +L: linux-media@vger.kernel.org S: Supported F: Documentation/devicetree/bindings/media/img,e5010-jpeg-enc.yaml +F: drivers/media/platform/imagination/e5010* IMGTEC IR DECODER DRIVER S: Orphan diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 2d79bfc68c15..6feeebab4b06 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -70,6 +70,7 @@ source "drivers/media/platform/atmel/Kconfig" source "drivers/media/platform/broadcom/Kconfig" source "drivers/media/platform/cadence/Kconfig" source "drivers/media/platform/chips-media/Kconfig" +source "drivers/media/platform/imagination/Kconfig" source "drivers/media/platform/intel/Kconfig" source "drivers/media/platform/marvell/Kconfig" source "drivers/media/platform/mediatek/Kconfig" diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile index da17301f7439..11a2f2d0c1a1 100644 --- a/drivers/media/platform/Makefile +++ b/drivers/media/platform/Makefile @@ -13,6 +13,7 @@ obj-y += atmel/ obj-y += broadcom/ obj-y += cadence/ obj-y += chips-media/ +obj-y += imagination/ obj-y += intel/ obj-y += marvell/ obj-y += mediatek/ diff --git a/drivers/media/platform/imagination/Kconfig b/drivers/media/platform/imagination/Kconfig new file mode 100644 index 000000000000..d8d79266ad5d --- /dev/null +++ b/drivers/media/platform/imagination/Kconfig @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0 +config VIDEO_E5010_JPEG_ENC + tristate "Imagination E5010 JPEG Encoder Driver" + depends on VIDEO_DEV + select VIDEOBUF2_DMA_CONTIG + select VIDEOBUF2_VMALLOC + select V4L2_MEM2MEM_DEV + help + This is a video4linux2 M2M driver for Imagination E5010 JPEG encoder, + which supports JPEG and MJPEG baseline encoding of YUV422 and YUV420 + semiplanar video formats, with resolution ranging from 64x64 to 8K x 8K + pixels. The module will be named as e5010_jpeg_enc. diff --git a/drivers/media/platform/imagination/Makefile b/drivers/media/platform/imagination/Makefile new file mode 100644 index 000000000000..d45b85b88575 --- /dev/null +++ b/drivers/media/platform/imagination/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 +e5010_jpeg_enc-objs := e5010-jpeg-enc-hw.o e5010-jpeg-enc.o +obj-$(CONFIG_VIDEO_E5010_JPEG_ENC) += e5010_jpeg_enc.o diff --git a/drivers/media/platform/imagination/e5010-core-regs.h b/drivers/media/platform/imagination/e5010-core-regs.h new file mode 100644 index 000000000000..aaec498fe83f --- /dev/null +++ b/drivers/media/platform/imagination/e5010-core-regs.h @@ -0,0 +1,585 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Imagination E5010 JPEG Encoder driver. + * + * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/ + * + * Author: David Huang + * Author: Devarsh Thakkar + */ + +#ifndef _E5010_CORE_REGS_H +#define _E5010_CORE_REGS_H + +#define JASPER_CORE_ID_OFFSET (0x0000) +#define JASPER_CORE_ID_CR_GROUP_ID_MASK (0xFF000000) +#define JASPER_CORE_ID_CR_GROUP_ID_SHIFT (24) +#define JASPER_CORE_ID_CR_CORE_ID_MASK (0x00FF0000) +#define JASPER_CORE_ID_CR_CORE_ID_SHIFT (16) +#define JASPER_CORE_ID_CR_UNIQUE_NUM_MASK (0x0000FFF8) +#define JASPER_CORE_ID_CR_UNIQUE_NUM_SHIFT (3) +#define JASPER_CORE_ID_CR_PELS_PER_CYCLE_MASK (0x00000007) +#define JASPER_CORE_ID_CR_PELS_PER_CYCLE_SHIFT (0) + +#define JASPER_CORE_REV_OFFSET (0x0004) +#define JASPER_CORE_REV_CR_JASPER_DESIGNER_MASK (0xFF000000) +#define JASPER_CORE_REV_CR_JASPER_DESIGNER_SHIFT (24) +#define JASPER_CORE_REV_CR_JASPER_MAJOR_REV_MASK (0x00FF0000) +#define JASPER_CORE_REV_CR_JASPER_MAJOR_REV_SHIFT (16) +#define JASPER_CORE_REV_CR_JASPER_MINOR_REV_MASK (0x0000FF00) +#define JASPER_CORE_REV_CR_JASPER_MINOR_REV_SHIFT (8) +#define JASPER_CORE_REV_CR_JASPER_MAINT_REV_MASK (0x000000FF) +#define JASPER_CORE_REV_CR_JASPER_MAINT_REV_SHIFT (0) + +#define JASPER_INTERRUPT_MASK_OFFSET (0x0008) +#define JASPER_INTERRUPT_MASK_CR_OUTPUT_ADDRESS_ERROR_ENABLE_MASK (0x00000002) +#define JASPER_INTERRUPT_MASK_CR_OUTPUT_ADDRESS_ERROR_ENABLE_SHIFT (1) +#define JASPER_INTERRUPT_MASK_CR_PICTURE_DONE_ENABLE_MASK (0x00000001) +#define JASPER_INTERRUPT_MASK_CR_PICTURE_DONE_ENABLE_SHIFT (0) + +#define JASPER_INTERRUPT_STATUS_OFFSET (0x000C) +#define JASPER_INTERRUPT_STATUS_CR_OUTPUT_ADDRESS_ERROR_IRQ_MASK (0x00000002) +#define JASPER_INTERRUPT_STATUS_CR_OUTPUT_ADDRESS_ERROR_IRQ_SHIFT (1) +#define JASPER_INTERRUPT_STATUS_CR_PICTURE_DONE_IRQ_MASK (0x00000001) +#define JASPER_INTERRUPT_STATUS_CR_PICTURE_DONE_IRQ_SHIFT (0) + +#define JASPER_INTERRUPT_CLEAR_OFFSET (0x0010) +#define JASPER_INTERRUPT_CLEAR_CR_OUTPUT_ERROR_CLEAR_MASK (0x00000002) +#define JASPER_INTERRUPT_CLEAR_CR_OUTPUT_ERROR_CLEAR_SHIFT (1) +#define JASPER_INTERRUPT_CLEAR_CR_PICTURE_DONE_CLEAR_MASK (0x00000001) +#define JASPER_INTERRUPT_CLEAR_CR_PICTURE_DONE_CLEAR_SHIFT (0) + +#define JASPER_CLK_CONTROL_OFFSET (0x0014) +#define JASPER_CLK_CONTROL_CR_JASPER_AUTO_CLKG_ENABLE_MASK (0x00000002) +#define JASPER_CLK_CONTROL_CR_JASPER_AUTO_CLKG_ENABLE_SHIFT (1) +#define JASPER_CLK_CONTROL_CR_JASPER_MAN_CLKG_ENABLE_MASK (0x00000001) +#define JASPER_CLK_CONTROL_CR_JASPER_MAN_CLKG_ENABLE_SHIFT (0) + +#define JASPER_CLK_STATUS_OFFSET (0x0018) +#define JASPER_CLK_STATUS_CR_JASPER_CLKG_STATUS_MASK (0x00000001) +#define JASPER_CLK_STATUS_CR_JASPER_CLKG_STATUS_SHIFT (0) + +#define JASPER_RESET_OFFSET (0x001C) +#define JASPER_RESET_CR_SYS_RESET_MASK (0x00000002) +#define JASPER_RESET_CR_SYS_RESET_SHIFT (1) +#define JASPER_RESET_CR_CORE_RESET_MASK (0x00000001) +#define JASPER_RESET_CR_CORE_RESET_SHIFT (0) + +#define JASPER_CORE_CTRL_OFFSET (0x0020) +#define JASPER_CORE_CTRL_CR_JASPER_ENCODE_START_MASK (0x00000001) +#define JASPER_CORE_CTRL_CR_JASPER_ENCODE_START_SHIFT (0) + +#define JASPER_STATUS_OFFSET (0x0024) +#define JASPER_STATUS_CR_FLUSH_MODE_MASK (0x00000002) +#define JASPER_STATUS_CR_FLUSH_MODE_SHIFT (1) +#define JASPER_STATUS_CR_JASPER_BUSY_MASK (0x00000001) +#define JASPER_STATUS_CR_JASPER_BUSY_SHIFT (0) + +#define JASPER_CRC_CLEAR_OFFSET (0x0028) +#define JASPER_CRC_CLEAR_CR_FRONT_END_CRC_CLEAR_MASK (0x00000001) +#define JASPER_CRC_CLEAR_CR_FRONT_END_CRC_CLEAR_SHIFT (0) +#define JASPER_CRC_CLEAR_CR_DCT_CRC_CLEAR_MASK (0x00000002) +#define JASPER_CRC_CLEAR_CR_DCT_CRC_CLEAR_SHIFT (1) +#define JASPER_CRC_CLEAR_CR_ZZ_CRC_CLEAR_MASK (0x00000004) +#define JASPER_CRC_CLEAR_CR_ZZ_CRC_CLEAR_SHIFT (2) +#define JASPER_CRC_CLEAR_CR_QUANT_CRC_CLEAR_MASK (0x00000008) +#define JASPER_CRC_CLEAR_CR_QUANT_CRC_CLEAR_SHIFT (3) +#define JASPER_CRC_CLEAR_CR_ENTROPY_ENCODER_CRC_CLEAR_MASK (0x00000010) +#define JASPER_CRC_CLEAR_CR_ENTROPY_ENCODER_CRC_CLEAR_SHIFT (4) +#define JASPER_CRC_CLEAR_CR_PACKING_BUFFER_CRC_CLEAR_MASK (0x00000020) +#define JASPER_CRC_CLEAR_CR_PACKING_BUFFER_CRC_CLEAR_SHIFT (5) + +#define JASPER_INPUT_CTRL0_OFFSET (0x002C) +#define JASPER_INPUT_CTRL0_CR_INPUT_CHROMA_ORDER_MASK (0x01000000) +#define JASPER_INPUT_CTRL0_CR_INPUT_CHROMA_ORDER_SHIFT (24) +#define JASPER_INPUT_CTRL0_CR_INPUT_SUBSAMPLING_MASK (0x00030000) +#define JASPER_INPUT_CTRL0_CR_INPUT_SUBSAMPLING_SHIFT (16) +#define JASPER_INPUT_CTRL0_CR_INPUT_SOURCE_MASK (0x00000004) +#define JASPER_INPUT_CTRL0_CR_INPUT_SOURCE_SHIFT (2) + +#define JASPER_INPUT_CTRL1_OFFSET (0x0030) +#define JASPER_INPUT_CTRL1_CR_INPUT_LUMA_STRIDE_MASK (0x1FC00000) +#define JASPER_INPUT_CTRL1_CR_INPUT_LUMA_STRIDE_SHIFT (22) +#define JASPER_INPUT_CTRL1_CR_INPUT_CHROMA_STRIDE_MASK (0x00001FC0) +#define JASPER_INPUT_CTRL1_CR_INPUT_CHROMA_STRIDE_SHIFT (6) + +#define JASPER_MMU_CTRL_OFFSET (0x0034) +#define JASPER_MMU_CTRL_CR_JASPER_TILING_SCHEME_MASK (0x00000002) +#define JASPER_MMU_CTRL_CR_JASPER_TILING_SCHEME_SHIFT (1) +#define JASPER_MMU_CTRL_CR_JASPER_TILING_ENABLE_MASK (0x00000001) +#define JASPER_MMU_CTRL_CR_JASPER_TILING_ENABLE_SHIFT (0) + +#define JASPER_IMAGE_SIZE_OFFSET (0x0038) +#define JASPER_IMAGE_SIZE_CR_IMAGE_VERTICAL_SIZE_MASK (0x1FFF0000) +#define JASPER_IMAGE_SIZE_CR_IMAGE_VERTICAL_SIZE_SHIFT (16) +#define JASPER_IMAGE_SIZE_CR_IMAGE_HORIZONTAL_SIZE_MASK (0x00001FFF) +#define JASPER_IMAGE_SIZE_CR_IMAGE_HORIZONTAL_SIZE_SHIFT (0) + +#define INPUT_LUMA_BASE_OFFSET (0x003C) +#define INPUT_LUMA_BASE_CR_INPUT_LUMA_BASE_MASK (0xFFFFFFC0) +#define INPUT_LUMA_BASE_CR_INPUT_LUMA_BASE_SHIFT (6) + +#define INPUT_CHROMA_BASE_OFFSET (0x0040) +#define INPUT_CHROMA_BASE_CR_INPUT_CHROMA_BASE_MASK (0xFFFFFFC0) +#define INPUT_CHROMA_BASE_CR_INPUT_CHROMA_BASE_SHIFT (6) + +#define JASPER_OUTPUT_BASE_OFFSET (0x0044) +#define JASPER_OUTPUT_BASE_CR_OUTPUT_BASE_MASK (0xFFFFFFFF) +#define JASPER_OUTPUT_BASE_CR_OUTPUT_BASE_SHIFT (0) + +#define JASPER_OUTPUT_SIZE_OFFSET (0x0048) +#define JASPER_OUTPUT_SIZE_CR_OUTPUT_SIZE_MASK (0xFFFFFFFF) +#define JASPER_OUTPUT_SIZE_CR_OUTPUT_SIZE_SHIFT (0) +#define JASPER_OUTPUT_MAX_SIZE_OFFSET (0x004C) +#define JASPER_OUTPUT_MAX_SIZE_CR_OUTPUT_MAX_SIZE_MASK (0xFFFFFFFF) +#define JASPER_OUTPUT_MAX_SIZE_CR_OUTPUT_MAX_SIZE_SHIFT (0) + +#define JASPER_LUMA_QUANTIZATION_TABLE0_OFFSET (0x0050) +#define JASPER_LUMA_QUANTIZATION_TABLE0_CR_LUMA_QUANTIZATION_TABLE_03_MASK (0xFF000000) +#define JASPER_LUMA_QUANTIZATION_TABLE0_CR_LUMA_QUANTIZATION_TABLE_03_SHIFT (24) +#define JASPER_LUMA_QUANTIZATION_TABLE0_CR_LUMA_QUANTIZATION_TABLE_02_MASK (0x00FF0000) +#define JASPER_LUMA_QUANTIZATION_TABLE0_CR_LUMA_QUANTIZATION_TABLE_02_SHIFT (16) +#define JASPER_LUMA_QUANTIZATION_TABLE0_CR_LUMA_QUANTIZATION_TABLE_01_MASK (0x0000FF00) +#define JASPER_LUMA_QUANTIZATION_TABLE0_CR_LUMA_QUANTIZATION_TABLE_01_SHIFT (8) +#define JASPER_LUMA_QUANTIZATION_TABLE0_CR_LUMA_QUANTIZATION_TABLE_00_MASK (0x000000FF) +#define JASPER_LUMA_QUANTIZATION_TABLE0_CR_LUMA_QUANTIZATION_TABLE_00_SHIFT (0) +#define JASPER_LUMA_QUANTIZATION_TABLE1_OFFSET (0x0054) +#define JASPER_LUMA_QUANTIZATION_TABLE1_CR_LUMA_QUANTIZATION_TABLE_07_MASK (0xFF000000) +#define JASPER_LUMA_QUANTIZATION_TABLE1_CR_LUMA_QUANTIZATION_TABLE_07_SHIFT (24) +#define JASPER_LUMA_QUANTIZATION_TABLE1_CR_LUMA_QUANTIZATION_TABLE_06_MASK (0x00FF0000) +#define JASPER_LUMA_QUANTIZATION_TABLE1_CR_LUMA_QUANTIZATION_TABLE_06_SHIFT (16) +#define JASPER_LUMA_QUANTIZATION_TABLE1_CR_LUMA_QUANTIZATION_TABLE_05_MASK (0x0000FF00) +#define JASPER_LUMA_QUANTIZATION_TABLE1_CR_LUMA_QUANTIZATION_TABLE_05_SHIFT (8) +#define JASPER_LUMA_QUANTIZATION_TABLE1_CR_LUMA_QUANTIZATION_TABLE_04_MASK (0x000000FF) +#define JASPER_LUMA_QUANTIZATION_TABLE1_CR_LUMA_QUANTIZATION_TABLE_04_SHIFT (0) +#define JASPER_LUMA_QUANTIZATION_TABLE2_OFFSET (0x0058) +#define JASPER_LUMA_QUANTIZATION_TABLE2_CR_LUMA_QUANTIZATION_TABLE_13_MASK (0xFF000000) +#define JASPER_LUMA_QUANTIZATION_TABLE2_CR_LUMA_QUANTIZATION_TABLE_13_SHIFT (24) +#define JASPER_LUMA_QUANTIZATION_TABLE2_CR_LUMA_QUANTIZATION_TABLE_12_MASK (0x00FF0000) +#define JASPER_LUMA_QUANTIZATION_TABLE2_CR_LUMA_QUANTIZATION_TABLE_12_SHIFT (16) +#define JASPER_LUMA_QUANTIZATION_TABLE2_CR_LUMA_QUANTIZATION_TABLE_11_MASK (0x0000FF00) +#define JASPER_LUMA_QUANTIZATION_TABLE2_CR_LUMA_QUANTIZATION_TABLE_11_SHIFT (8) +#define JASPER_LUMA_QUANTIZATION_TABLE2_CR_LUMA_QUANTIZATION_TABLE_10_MASK (0x000000FF) +#define JASPER_LUMA_QUANTIZATION_TABLE2_CR_LUMA_QUANTIZATION_TABLE_10_SHIFT (0) +#define JASPER_LUMA_QUANTIZATION_TABLE3_OFFSET (0x005C) +#define JASPER_LUMA_QUANTIZATION_TABLE3_CR_LUMA_QUANTIZATION_TABLE_17_MASK (0xFF000000) +#define JASPER_LUMA_QUANTIZATION_TABLE3_CR_LUMA_QUANTIZATION_TABLE_17_SHIFT (24) +#define JASPER_LUMA_QUANTIZATION_TABLE3_CR_LUMA_QUANTIZATION_TABLE_16_MASK (0x00FF0000) +#define JASPER_LUMA_QUANTIZATION_TABLE3_CR_LUMA_QUANTIZATION_TABLE_16_SHIFT (16) +#define JASPER_LUMA_QUANTIZATION_TABLE3_CR_LUMA_QUANTIZATION_TABLE_15_MASK (0x0000FF00) +#define JASPER_LUMA_QUANTIZATION_TABLE3_CR_LUMA_QUANTIZATION_TABLE_15_SHIFT (8) +#define JASPER_LUMA_QUANTIZATION_TABLE3_CR_LUMA_QUANTIZATION_TABLE_14_MASK (0x000000FF) +#define JASPER_LUMA_QUANTIZATION_TABLE3_CR_LUMA_QUANTIZATION_TABLE_14_SHIFT (0) +#define JASPER_LUMA_QUANTIZATION_TABLE4_OFFSET (0x0060) +#define JASPER_LUMA_QUANTIZATION_TABLE4_CR_LUMA_QUANTIZATION_TABLE_21_MASK (0x0000FF00) +#define JASPER_LUMA_QUANTIZATION_TABLE4_CR_LUMA_QUANTIZATION_TABLE_21_SHIFT (8) +#define JASPER_LUMA_QUANTIZATION_TABLE4_CR_LUMA_QUANTIZATION_TABLE_20_MASK (0x000000FF) +#define JASPER_LUMA_QUANTIZATION_TABLE4_CR_LUMA_QUANTIZATION_TABLE_20_SHIFT (0) + +#define JASPER_LUMA_QUANTIZATION_TABLE5_OFFSET (0x0064) +#define JASPER_LUMA_QUANTIZATION_TABLE5_CR_LUMA_QUANTIZATION_TABLE_27_MASK (0xFF000000) +#define JASPER_LUMA_QUANTIZATION_TABLE5_CR_LUMA_QUANTIZATION_TABLE_27_SHIFT (24) +#define JASPER_LUMA_QUANTIZATION_TABLE5_CR_LUMA_QUANTIZATION_TABLE_26_MASK (0x00FF0000) +#define JASPER_LUMA_QUANTIZATION_TABLE5_CR_LUMA_QUANTIZATION_TABLE_26_SHIFT (16) +#define JASPER_LUMA_QUANTIZATION_TABLE5_CR_LUMA_QUANTIZATION_TABLE_25_MASK (0x0000FF00) +#define JASPER_LUMA_QUANTIZATION_TABLE5_CR_LUMA_QUANTIZATION_TABLE_25_SHIFT (8) +#define JASPER_LUMA_QUANTIZATION_TABLE5_CR_LUMA_QUANTIZATION_TABLE_24_MASK (0x000000FF) +#define JASPER_LUMA_QUANTIZATION_TABLE5_CR_LUMA_QUANTIZATION_TABLE_24_SHIFT (0) + +#define JASPER_LUMA_QUANTIZATION_TABLE6_OFFSET (0x0068) + +#define JASPER_LUMA_QUANTIZATION_TABLE6_CR_LUMA_QUANTIZATION_TABLE_33_MASK (0xFF000000) +#define JASPER_LUMA_QUANTIZATION_TABLE6_CR_LUMA_QUANTIZATION_TABLE_33_SHIFT (24) + +#define JASPER_LUMA_QUANTIZATION_TABLE6_CR_LUMA_QUANTIZATION_TABLE_32_MASK (0x00FF0000) +#define JASPER_LUMA_QUANTIZATION_TABLE6_CR_LUMA_QUANTIZATION_TABLE_32_SHIFT (16) + +#define JASPER_LUMA_QUANTIZATION_TABLE6_CR_LUMA_QUANTIZATION_TABLE_31_MASK (0x0000FF00) +#define JASPER_LUMA_QUANTIZATION_TABLE6_CR_LUMA_QUANTIZATION_TABLE_31_SHIFT (8) +#define JASPER_LUMA_QUANTIZATION_TABLE6_CR_LUMA_QUANTIZATION_TABLE_30_MASK (0x000000FF) +#define JASPER_LUMA_QUANTIZATION_TABLE6_CR_LUMA_QUANTIZATION_TABLE_30_SHIFT (0) + +#define JASPER_LUMA_QUANTIZATION_TABLE7_OFFSET (0x006C) + +#define JASPER_LUMA_QUANTIZATION_TABLE7_CR_LUMA_QUANTIZATION_TABLE_37_MASK (0xFF000000) +#define JASPER_LUMA_QUANTIZATION_TABLE7_CR_LUMA_QUANTIZATION_TABLE_37_SHIFT (24) + +#define JASPER_LUMA_QUANTIZATION_TABLE7_CR_LUMA_QUANTIZATION_TABLE_36_MASK (0x00FF0000) +#define JASPER_LUMA_QUANTIZATION_TABLE7_CR_LUMA_QUANTIZATION_TABLE_36_SHIFT (16) + +#define JASPER_LUMA_QUANTIZATION_TABLE7_CR_LUMA_QUANTIZATION_TABLE_35_MASK (0x0000FF00) +#define JASPER_LUMA_QUANTIZATION_TABLE7_CR_LUMA_QUANTIZATION_TABLE_35_SHIFT (8) + +#define JASPER_LUMA_QUANTIZATION_TABLE7_CR_LUMA_QUANTIZATION_TABLE_34_MASK (0x000000FF) +#define JASPER_LUMA_QUANTIZATION_TABLE7_CR_LUMA_QUANTIZATION_TABLE_34_SHIFT (0) + +#define JASPER_LUMA_QUANTIZATION_TABLE8_OFFSET (0x0070) + +#define JASPER_LUMA_QUANTIZATION_TABLE8_CR_LUMA_QUANTIZATION_TABLE_43_MASK (0xFF000000) +#define JASPER_LUMA_QUANTIZATION_TABLE8_CR_LUMA_QUANTIZATION_TABLE_43_SHIFT (24) +#define JASPER_LUMA_QUANTIZATION_TABLE8_CR_LUMA_QUANTIZATION_TABLE_42_MASK (0x00FF0000) +#define JASPER_LUMA_QUANTIZATION_TABLE8_CR_LUMA_QUANTIZATION_TABLE_42_SHIFT (16) + +#define JASPER_LUMA_QUANTIZATION_TABLE8_CR_LUMA_QUANTIZATION_TABLE_41_MASK (0x0000FF00) +#define JASPER_LUMA_QUANTIZATION_TABLE8_CR_LUMA_QUANTIZATION_TABLE_41_SHIFT (8) + +#define JASPER_LUMA_QUANTIZATION_TABLE8_CR_LUMA_QUANTIZATION_TABLE_40_MASK (0x000000FF) +#define JASPER_LUMA_QUANTIZATION_TABLE8_CR_LUMA_QUANTIZATION_TABLE_40_SHIFT (0) + +#define JASPER_LUMA_QUANTIZATION_TABLE9_OFFSET (0x0074) + +#define JASPER_LUMA_QUANTIZATION_TABLE9_CR_LUMA_QUANTIZATION_TABLE_47_MASK (0xFF000000) +#define JASPER_LUMA_QUANTIZATION_TABLE9_CR_LUMA_QUANTIZATION_TABLE_47_SHIFT (24) + +#define JASPER_LUMA_QUANTIZATION_TABLE9_CR_LUMA_QUANTIZATION_TABLE_46_MASK (0x00FF0000) +#define JASPER_LUMA_QUANTIZATION_TABLE9_CR_LUMA_QUANTIZATION_TABLE_46_SHIFT (16) + +#define JASPER_LUMA_QUANTIZATION_TABLE9_CR_LUMA_QUANTIZATION_TABLE_45_MASK (0x0000FF00) +#define JASPER_LUMA_QUANTIZATION_TABLE9_CR_LUMA_QUANTIZATION_TABLE_45_SHIFT (8) + +#define JASPER_LUMA_QUANTIZATION_TABLE9_CR_LUMA_QUANTIZATION_TABLE_44_MASK (0x000000FF) +#define JASPER_LUMA_QUANTIZATION_TABLE9_CR_LUMA_QUANTIZATION_TABLE_44_SHIFT (0) + +#define JASPER_LUMA_QUANTIZATION_TABLE10_OFFSET (0x0078) + +#define JASPER_LUMA_QUANTIZATION_TABLE10_CR_LUMA_QUANTIZATION_TABLE_53_MASK (0xFF000000) +#define JASPER_LUMA_QUANTIZATION_TABLE10_CR_LUMA_QUANTIZATION_TABLE_53_SHIFT (24) + +#define JASPER_LUMA_QUANTIZATION_TABLE10_CR_LUMA_QUANTIZATION_TABLE_52_MASK (0x00FF0000) +#define JASPER_LUMA_QUANTIZATION_TABLE10_CR_LUMA_QUANTIZATION_TABLE_52_SHIFT (16) + +#define JASPER_LUMA_QUANTIZATION_TABLE10_CR_LUMA_QUANTIZATION_TABLE_51_MASK (0x0000FF00) +#define JASPER_LUMA_QUANTIZATION_TABLE10_CR_LUMA_QUANTIZATION_TABLE_51_SHIFT (8) + +#define JASPER_LUMA_QUANTIZATION_TABLE10_CR_LUMA_QUANTIZATION_TABLE_50_MASK (0x000000FF) +#define JASPER_LUMA_QUANTIZATION_TABLE10_CR_LUMA_QUANTIZATION_TABLE_50_SHIFT (0) + +#define JASPER_LUMA_QUANTIZATION_TABLE11_OFFSET (0x007C) + +#define JASPER_LUMA_QUANTIZATION_TABLE11_CR_LUMA_QUANTIZATION_TABLE_57_MASK (0xFF000000) +#define JASPER_LUMA_QUANTIZATION_TABLE11_CR_LUMA_QUANTIZATION_TABLE_57_SHIFT (24) + +#define JASPER_LUMA_QUANTIZATION_TABLE11_CR_LUMA_QUANTIZATION_TABLE_56_MASK (0x00FF0000) +#define JASPER_LUMA_QUANTIZATION_TABLE11_CR_LUMA_QUANTIZATION_TABLE_56_SHIFT (16) + +#define JASPER_LUMA_QUANTIZATION_TABLE11_CR_LUMA_QUANTIZATION_TABLE_55_MASK (0x0000FF00) +#define JASPER_LUMA_QUANTIZATION_TABLE11_CR_LUMA_QUANTIZATION_TABLE_55_SHIFT (8) + +#define JASPER_LUMA_QUANTIZATION_TABLE11_CR_LUMA_QUANTIZATION_TABLE_54_MASK (0x000000FF) +#define JASPER_LUMA_QUANTIZATION_TABLE11_CR_LUMA_QUANTIZATION_TABLE_54_SHIFT (0) + +#define JASPER_LUMA_QUANTIZATION_TABLE12_OFFSET (0x0080) + +#define JASPER_LUMA_QUANTIZATION_TABLE12_CR_LUMA_QUANTIZATION_TABLE_63_MASK (0xFF000000) +#define JASPER_LUMA_QUANTIZATION_TABLE12_CR_LUMA_QUANTIZATION_TABLE_63_SHIFT (24) + +#define JASPER_LUMA_QUANTIZATION_TABLE12_CR_LUMA_QUANTIZATION_TABLE_62_MASK (0x00FF0000) +#define JASPER_LUMA_QUANTIZATION_TABLE12_CR_LUMA_QUANTIZATION_TABLE_62_SHIFT (16) + +#define JASPER_LUMA_QUANTIZATION_TABLE12_CR_LUMA_QUANTIZATION_TABLE_61_MASK (0x0000FF00) +#define JASPER_LUMA_QUANTIZATION_TABLE12_CR_LUMA_QUANTIZATION_TABLE_61_SHIFT (8) + +#define JASPER_LUMA_QUANTIZATION_TABLE12_CR_LUMA_QUANTIZATION_TABLE_60_MASK (0x000000FF) +#define JASPER_LUMA_QUANTIZATION_TABLE12_CR_LUMA_QUANTIZATION_TABLE_60_SHIFT (0) + +#define JASPER_LUMA_QUANTIZATION_TABLE13_OFFSET (0x0084) + +#define JASPER_LUMA_QUANTIZATION_TABLE13_CR_LUMA_QUANTIZATION_TABLE_67_MASK (0xFF000000) +#define JASPER_LUMA_QUANTIZATION_TABLE13_CR_LUMA_QUANTIZATION_TABLE_67_SHIFT (24) + +#define JASPER_LUMA_QUANTIZATION_TABLE13_CR_LUMA_QUANTIZATION_TABLE_66_MASK (0x00FF0000) +#define JASPER_LUMA_QUANTIZATION_TABLE13_CR_LUMA_QUANTIZATION_TABLE_66_SHIFT (16) + +#define JASPER_LUMA_QUANTIZATION_TABLE13_CR_LUMA_QUANTIZATION_TABLE_65_MASK (0x0000FF00) +#define JASPER_LUMA_QUANTIZATION_TABLE13_CR_LUMA_QUANTIZATION_TABLE_65_SHIFT (8) + +#define JASPER_LUMA_QUANTIZATION_TABLE13_CR_LUMA_QUANTIZATION_TABLE_64_MASK (0x000000FF) +#define JASPER_LUMA_QUANTIZATION_TABLE13_CR_LUMA_QUANTIZATION_TABLE_64_SHIFT (0) + +#define JASPER_LUMA_QUANTIZATION_TABLE14_OFFSET (0x0088) + +#define JASPER_LUMA_QUANTIZATION_TABLE14_CR_LUMA_QUANTIZATION_TABLE_73_MASK (0xFF000000) +#define JASPER_LUMA_QUANTIZATION_TABLE14_CR_LUMA_QUANTIZATION_TABLE_73_SHIFT (24) + +#define JASPER_LUMA_QUANTIZATION_TABLE14_CR_LUMA_QUANTIZATION_TABLE_72_MASK (0x00FF0000) +#define JASPER_LUMA_QUANTIZATION_TABLE14_CR_LUMA_QUANTIZATION_TABLE_72_SHIFT (16) + +#define JASPER_LUMA_QUANTIZATION_TABLE14_CR_LUMA_QUANTIZATION_TABLE_71_MASK (0x0000FF00) +#define JASPER_LUMA_QUANTIZATION_TABLE14_CR_LUMA_QUANTIZATION_TABLE_71_SHIFT (8) + +#define JASPER_LUMA_QUANTIZATION_TABLE14_CR_LUMA_QUANTIZATION_TABLE_70_MASK (0x000000FF) +#define JASPER_LUMA_QUANTIZATION_TABLE14_CR_LUMA_QUANTIZATION_TABLE_70_SHIFT (0) + +#define JASPER_LUMA_QUANTIZATION_TABLE15_OFFSET (0x008C) + +#define JASPER_LUMA_QUANTIZATION_TABLE15_CR_LUMA_QUANTIZATION_TABLE_77_MASK (0xFF000000) +#define JASPER_LUMA_QUANTIZATION_TABLE15_CR_LUMA_QUANTIZATION_TABLE_77_SHIFT (24) + +#define JASPER_LUMA_QUANTIZATION_TABLE15_CR_LUMA_QUANTIZATION_TABLE_76_MASK (0x00FF0000) +#define JASPER_LUMA_QUANTIZATION_TABLE15_CR_LUMA_QUANTIZATION_TABLE_76_SHIFT (16) + +#define JASPER_LUMA_QUANTIZATION_TABLE15_CR_LUMA_QUANTIZATION_TABLE_75_MASK (0x0000FF00) +#define JASPER_LUMA_QUANTIZATION_TABLE15_CR_LUMA_QUANTIZATION_TABLE_75_SHIFT (8) + +#define JASPER_LUMA_QUANTIZATION_TABLE15_CR_LUMA_QUANTIZATION_TABLE_74_MASK (0x000000FF) +#define JASPER_LUMA_QUANTIZATION_TABLE15_CR_LUMA_QUANTIZATION_TABLE_74_SHIFT (0) + +#define JASPER_CHROMA_QUANTIZATION_TABLE0_OFFSET (0x0090) + +#define JASPER_CHROMA_QUANTIZATION_TABLE0_CR_CHROMA_QUANTIZATION_TABLE_03_MASK (0xFF000000) +#define JASPER_CHROMA_QUANTIZATION_TABLE0_CR_CHROMA_QUANTIZATION_TABLE_03_SHIFT (24) + +#define JASPER_CHROMA_QUANTIZATION_TABLE0_CR_CHROMA_QUANTIZATION_TABLE_02_MASK (0x00FF0000) +#define JASPER_CHROMA_QUANTIZATION_TABLE0_CR_CHROMA_QUANTIZATION_TABLE_02_SHIFT (16) + +#define JASPER_CHROMA_QUANTIZATION_TABLE0_CR_CHROMA_QUANTIZATION_TABLE_01_MASK (0x0000FF00) +#define JASPER_CHROMA_QUANTIZATION_TABLE0_CR_CHROMA_QUANTIZATION_TABLE_01_SHIFT (8) + +#define JASPER_CHROMA_QUANTIZATION_TABLE0_CR_CHROMA_QUANTIZATION_TABLE_00_MASK (0x000000FF) +#define JASPER_CHROMA_QUANTIZATION_TABLE0_CR_CHROMA_QUANTIZATION_TABLE_00_SHIFT (0) + +#define JASPER_CHROMA_QUANTIZATION_TABLE1_OFFSET (0x0094) + +#define JASPER_CHROMA_QUANTIZATION_TABLE1_CR_CHROMA_QUANTIZATION_TABLE_07_MASK (0xFF000000) +#define JASPER_CHROMA_QUANTIZATION_TABLE1_CR_CHROMA_QUANTIZATION_TABLE_07_SHIFT (24) + +#define JASPER_CHROMA_QUANTIZATION_TABLE1_CR_CHROMA_QUANTIZATION_TABLE_06_MASK (0x00FF0000) +#define JASPER_CHROMA_QUANTIZATION_TABLE1_CR_CHROMA_QUANTIZATION_TABLE_06_SHIFT (16) + +#define JASPER_CHROMA_QUANTIZATION_TABLE1_CR_CHROMA_QUANTIZATION_TABLE_05_MASK (0x0000FF00) +#define JASPER_CHROMA_QUANTIZATION_TABLE1_CR_CHROMA_QUANTIZATION_TABLE_05_SHIFT (8) + +#define JASPER_CHROMA_QUANTIZATION_TABLE1_CR_CHROMA_QUANTIZATION_TABLE_04_MASK (0x000000FF) +#define JASPER_CHROMA_QUANTIZATION_TABLE1_CR_CHROMA_QUANTIZATION_TABLE_04_SHIFT (0) + +#define JASPER_CHROMA_QUANTIZATION_TABLE2_OFFSET (0x0098) + +#define JASPER_CHROMA_QUANTIZATION_TABLE2_CR_CHROMA_QUANTIZATION_TABLE_13_MASK (0xFF000000) +#define JASPER_CHROMA_QUANTIZATION_TABLE2_CR_CHROMA_QUANTIZATION_TABLE_13_SHIFT (24) + +#define JASPER_CHROMA_QUANTIZATION_TABLE2_CR_CHROMA_QUANTIZATION_TABLE_12_MASK (0x00FF0000) +#define JASPER_CHROMA_QUANTIZATION_TABLE2_CR_CHROMA_QUANTIZATION_TABLE_12_SHIFT (16) + +#define JASPER_CHROMA_QUANTIZATION_TABLE2_CR_CHROMA_QUANTIZATION_TABLE_11_MASK (0x0000FF00) +#define JASPER_CHROMA_QUANTIZATION_TABLE2_CR_CHROMA_QUANTIZATION_TABLE_11_SHIFT (8) + +#define JASPER_CHROMA_QUANTIZATION_TABLE2_CR_CHROMA_QUANTIZATION_TABLE_10_MASK (0x000000FF) +#define JASPER_CHROMA_QUANTIZATION_TABLE2_CR_CHROMA_QUANTIZATION_TABLE_10_SHIFT (0) + +#define JASPER_CHROMA_QUANTIZATION_TABLE3_OFFSET (0x009C) + +#define JASPER_CHROMA_QUANTIZATION_TABLE3_CR_CHROMA_QUANTIZATION_TABLE_17_MASK (0xFF000000) +#define JASPER_CHROMA_QUANTIZATION_TABLE3_CR_CHROMA_QUANTIZATION_TABLE_17_SHIFT (24) + +#define JASPER_CHROMA_QUANTIZATION_TABLE3_CR_CHROMA_QUANTIZATION_TABLE_16_MASK (0x00FF0000) +#define JASPER_CHROMA_QUANTIZATION_TABLE3_CR_CHROMA_QUANTIZATION_TABLE_16_SHIFT (16) + +#define JASPER_CHROMA_QUANTIZATION_TABLE3_CR_CHROMA_QUANTIZATION_TABLE_15_MASK (0x0000FF00) +#define JASPER_CHROMA_QUANTIZATION_TABLE3_CR_CHROMA_QUANTIZATION_TABLE_15_SHIFT (8) + +#define JASPER_CHROMA_QUANTIZATION_TABLE3_CR_CHROMA_QUANTIZATION_TABLE_14_MASK (0x000000FF) +#define JASPER_CHROMA_QUANTIZATION_TABLE3_CR_CHROMA_QUANTIZATION_TABLE_14_SHIFT (0) + +#define JASPER_CHROMA_QUANTIZATION_TABLE4_OFFSET (0x00A0) + +#define JASPER_CHROMA_QUANTIZATION_TABLE4_CR_CHROMA_QUANTIZATION_TABLE_23_MASK (0xFF000000) +#define JASPER_CHROMA_QUANTIZATION_TABLE4_CR_CHROMA_QUANTIZATION_TABLE_23_SHIFT (24) + +#define JASPER_CHROMA_QUANTIZATION_TABLE4_CR_CHROMA_QUANTIZATION_TABLE_22_MASK (0x00FF0000) +#define JASPER_CHROMA_QUANTIZATION_TABLE4_CR_CHROMA_QUANTIZATION_TABLE_22_SHIFT (16) + +#define JASPER_CHROMA_QUANTIZATION_TABLE4_CR_CHROMA_QUANTIZATION_TABLE_21_MASK (0x0000FF00) +#define JASPER_CHROMA_QUANTIZATION_TABLE4_CR_CHROMA_QUANTIZATION_TABLE_21_SHIFT (8) + +#define JASPER_CHROMA_QUANTIZATION_TABLE4_CR_CHROMA_QUANTIZATION_TABLE_20_MASK (0x000000FF) +#define JASPER_CHROMA_QUANTIZATION_TABLE4_CR_CHROMA_QUANTIZATION_TABLE_20_SHIFT (0) + +#define JASPER_CHROMA_QUANTIZATION_TABLE5_OFFSET (0x00A4) + +#define JASPER_CHROMA_QUANTIZATION_TABLE5_CR_CHROMA_QUANTIZATION_TABLE_27_MASK (0xFF000000) +#define JASPER_CHROMA_QUANTIZATION_TABLE5_CR_CHROMA_QUANTIZATION_TABLE_27_SHIFT (24) + +#define JASPER_CHROMA_QUANTIZATION_TABLE5_CR_CHROMA_QUANTIZATION_TABLE_26_MASK (0x00FF0000) +#define JASPER_CHROMA_QUANTIZATION_TABLE5_CR_CHROMA_QUANTIZATION_TABLE_26_SHIFT (16) + +#define JASPER_CHROMA_QUANTIZATION_TABLE5_CR_CHROMA_QUANTIZATION_TABLE_25_MASK (0x0000FF00) +#define JASPER_CHROMA_QUANTIZATION_TABLE5_CR_CHROMA_QUANTIZATION_TABLE_25_SHIFT (8) + +#define JASPER_CHROMA_QUANTIZATION_TABLE5_CR_CHROMA_QUANTIZATION_TABLE_24_MASK (0x000000FF) +#define JASPER_CHROMA_QUANTIZATION_TABLE5_CR_CHROMA_QUANTIZATION_TABLE_24_SHIFT (0) + +#define JASPER_CHROMA_QUANTIZATION_TABLE6_OFFSET (0x00A8) + +#define JASPER_CHROMA_QUANTIZATION_TABLE6_CR_CHROMA_QUANTIZATION_TABLE_33_MASK (0xFF000000) +#define JASPER_CHROMA_QUANTIZATION_TABLE6_CR_CHROMA_QUANTIZATION_TABLE_33_SHIFT (24) + +#define JASPER_CHROMA_QUANTIZATION_TABLE6_CR_CHROMA_QUANTIZATION_TABLE_32_MASK (0x00FF0000) +#define JASPER_CHROMA_QUANTIZATION_TABLE6_CR_CHROMA_QUANTIZATION_TABLE_32_SHIFT (16) + +#define JASPER_CHROMA_QUANTIZATION_TABLE6_CR_CHROMA_QUANTIZATION_TABLE_31_MASK (0x0000FF00) +#define JASPER_CHROMA_QUANTIZATION_TABLE6_CR_CHROMA_QUANTIZATION_TABLE_31_SHIFT (8) + +#define JASPER_CHROMA_QUANTIZATION_TABLE6_CR_CHROMA_QUANTIZATION_TABLE_30_MASK (0x000000FF) +#define JASPER_CHROMA_QUANTIZATION_TABLE6_CR_CHROMA_QUANTIZATION_TABLE_30_SHIFT (0) + +#define JASPER_CHROMA_QUANTIZATION_TABLE7_OFFSET (0x00AC) + +#define JASPER_CHROMA_QUANTIZATION_TABLE7_CR_CHROMA_QUANTIZATION_TABLE_37_MASK (0xFF000000) +#define JASPER_CHROMA_QUANTIZATION_TABLE7_CR_CHROMA_QUANTIZATION_TABLE_37_SHIFT (24) + +#define JASPER_CHROMA_QUANTIZATION_TABLE7_CR_CHROMA_QUANTIZATION_TABLE_36_MASK (0x00FF0000) +#define JASPER_CHROMA_QUANTIZATION_TABLE7_CR_CHROMA_QUANTIZATION_TABLE_36_SHIFT (16) + +#define JASPER_CHROMA_QUANTIZATION_TABLE7_CR_CHROMA_QUANTIZATION_TABLE_35_MASK (0x0000FF00) +#define JASPER_CHROMA_QUANTIZATION_TABLE7_CR_CHROMA_QUANTIZATION_TABLE_35_SHIFT (8) + +#define JASPER_CHROMA_QUANTIZATION_TABLE7_CR_CHROMA_QUANTIZATION_TABLE_34_MASK (0x000000FF) +#define JASPER_CHROMA_QUANTIZATION_TABLE7_CR_CHROMA_QUANTIZATION_TABLE_34_SHIFT (0) + +#define JASPER_CHROMA_QUANTIZATION_TABLE8_OFFSET (0x00B0) + +#define JASPER_CHROMA_QUANTIZATION_TABLE8_CR_CHROMA_QUANTIZATION_TABLE_43_MASK (0xFF000000) +#define JASPER_CHROMA_QUANTIZATION_TABLE8_CR_CHROMA_QUANTIZATION_TABLE_43_SHIFT (24) + +#define JASPER_CHROMA_QUANTIZATION_TABLE8_CR_CHROMA_QUANTIZATION_TABLE_42_MASK (0x00FF0000) +#define JASPER_CHROMA_QUANTIZATION_TABLE8_CR_CHROMA_QUANTIZATION_TABLE_42_SHIFT (16) + +#define JASPER_CHROMA_QUANTIZATION_TABLE8_CR_CHROMA_QUANTIZATION_TABLE_41_MASK (0x0000FF00) +#define JASPER_CHROMA_QUANTIZATION_TABLE8_CR_CHROMA_QUANTIZATION_TABLE_41_SHIFT (8) + +#define JASPER_CHROMA_QUANTIZATION_TABLE8_CR_CHROMA_QUANTIZATION_TABLE_40_MASK (0x000000FF) +#define JASPER_CHROMA_QUANTIZATION_TABLE8_CR_CHROMA_QUANTIZATION_TABLE_40_SHIFT (0) + +#define JASPER_CHROMA_QUANTIZATION_TABLE9_OFFSET (0x00B4) + +#define JASPER_CHROMA_QUANTIZATION_TABLE9_CR_CHROMA_QUANTIZATION_TABLE_47_MASK (0xFF000000) +#define JASPER_CHROMA_QUANTIZATION_TABLE9_CR_CHROMA_QUANTIZATION_TABLE_47_SHIFT (24) + +#define JASPER_CHROMA_QUANTIZATION_TABLE9_CR_CHROMA_QUANTIZATION_TABLE_46_MASK (0x00FF0000) +#define JASPER_CHROMA_QUANTIZATION_TABLE9_CR_CHROMA_QUANTIZATION_TABLE_46_SHIFT (16) + +#define JASPER_CHROMA_QUANTIZATION_TABLE9_CR_CHROMA_QUANTIZATION_TABLE_45_MASK (0x0000FF00) +#define JASPER_CHROMA_QUANTIZATION_TABLE9_CR_CHROMA_QUANTIZATION_TABLE_45_SHIFT (8) + +#define JASPER_CHROMA_QUANTIZATION_TABLE9_CR_CHROMA_QUANTIZATION_TABLE_44_MASK (0x000000FF) +#define JASPER_CHROMA_QUANTIZATION_TABLE9_CR_CHROMA_QUANTIZATION_TABLE_44_SHIFT (0) + +#define JASPER_CHROMA_QUANTIZATION_TABLE10_OFFSET (0x00B8) + +#define JASPER_CHROMA_QUANTIZATION_TABLE10_CR_CHROMA_QUANTIZATION_TABLE_53_MASK (0xFF000000) +#define JASPER_CHROMA_QUANTIZATION_TABLE10_CR_CHROMA_QUANTIZATION_TABLE_53_SHIFT (24) + +#define JASPER_CHROMA_QUANTIZATION_TABLE10_CR_CHROMA_QUANTIZATION_TABLE_52_MASK (0x00FF0000) +#define JASPER_CHROMA_QUANTIZATION_TABLE10_CR_CHROMA_QUANTIZATION_TABLE_52_SHIFT (16) + +#define JASPER_CHROMA_QUANTIZATION_TABLE10_CR_CHROMA_QUANTIZATION_TABLE_51_MASK (0x0000FF00) +#define JASPER_CHROMA_QUANTIZATION_TABLE10_CR_CHROMA_QUANTIZATION_TABLE_51_SHIFT (8) + +#define JASPER_CHROMA_QUANTIZATION_TABLE10_CR_CHROMA_QUANTIZATION_TABLE_50_MASK (0x000000FF) +#define JASPER_CHROMA_QUANTIZATION_TABLE10_CR_CHROMA_QUANTIZATION_TABLE_50_SHIFT (0) + +#define JASPER_CHROMA_QUANTIZATION_TABLE11_OFFSET (0x00BC) + +#define JASPER_CHROMA_QUANTIZATION_TABLE11_CR_CHROMA_QUANTIZATION_TABLE_57_MASK (0xFF000000) +#define JASPER_CHROMA_QUANTIZATION_TABLE11_CR_CHROMA_QUANTIZATION_TABLE_57_SHIFT (24) + +#define JASPER_CHROMA_QUANTIZATION_TABLE11_CR_CHROMA_QUANTIZATION_TABLE_56_MASK (0x00FF0000) +#define JASPER_CHROMA_QUANTIZATION_TABLE11_CR_CHROMA_QUANTIZATION_TABLE_56_SHIFT (16) + +#define JASPER_CHROMA_QUANTIZATION_TABLE11_CR_CHROMA_QUANTIZATION_TABLE_55_MASK (0x0000FF00) +#define JASPER_CHROMA_QUANTIZATION_TABLE11_CR_CHROMA_QUANTIZATION_TABLE_55_SHIFT (8) + +#define JASPER_CHROMA_QUANTIZATION_TABLE11_CR_CHROMA_QUANTIZATION_TABLE_54_MASK (0x000000FF) +#define JASPER_CHROMA_QUANTIZATION_TABLE11_CR_CHROMA_QUANTIZATION_TABLE_54_SHIFT (0) + +#define JASPER_CHROMA_QUANTIZATION_TABLE12_OFFSET (0x00C0) + +#define JASPER_CHROMA_QUANTIZATION_TABLE12_CR_CHROMA_QUANTIZATION_TABLE_63_MASK (0xFF000000) +#define JASPER_CHROMA_QUANTIZATION_TABLE12_CR_CHROMA_QUANTIZATION_TABLE_63_SHIFT (24) + +#define JASPER_CHROMA_QUANTIZATION_TABLE12_CR_CHROMA_QUANTIZATION_TABLE_62_MASK (0x00FF0000) +#define JASPER_CHROMA_QUANTIZATION_TABLE12_CR_CHROMA_QUANTIZATION_TABLE_62_SHIFT (16) + +#define JASPER_CHROMA_QUANTIZATION_TABLE12_CR_CHROMA_QUANTIZATION_TABLE_61_MASK (0x0000FF00) +#define JASPER_CHROMA_QUANTIZATION_TABLE12_CR_CHROMA_QUANTIZATION_TABLE_61_SHIFT (8) + +#define JASPER_CHROMA_QUANTIZATION_TABLE12_CR_CHROMA_QUANTIZATION_TABLE_60_MASK (0x000000FF) +#define JASPER_CHROMA_QUANTIZATION_TABLE12_CR_CHROMA_QUANTIZATION_TABLE_60_SHIFT (0) + +#define JASPER_CHROMA_QUANTIZATION_TABLE13_OFFSET (0x00C4) + +#define JASPER_CHROMA_QUANTIZATION_TABLE13_CR_CHROMA_QUANTIZATION_TABLE_67_MASK (0xFF000000) +#define JASPER_CHROMA_QUANTIZATION_TABLE13_CR_CHROMA_QUANTIZATION_TABLE_67_SHIFT (24) + +#define JASPER_CHROMA_QUANTIZATION_TABLE13_CR_CHROMA_QUANTIZATION_TABLE_66_MASK (0x00FF0000) +#define JASPER_CHROMA_QUANTIZATION_TABLE13_CR_CHROMA_QUANTIZATION_TABLE_66_SHIFT (16) + +#define JASPER_CHROMA_QUANTIZATION_TABLE13_CR_CHROMA_QUANTIZATION_TABLE_65_MASK (0x0000FF00) +#define JASPER_CHROMA_QUANTIZATION_TABLE13_CR_CHROMA_QUANTIZATION_TABLE_65_SHIFT (8) + +#define JASPER_CHROMA_QUANTIZATION_TABLE13_CR_CHROMA_QUANTIZATION_TABLE_64_MASK (0x000000FF) +#define JASPER_CHROMA_QUANTIZATION_TABLE13_CR_CHROMA_QUANTIZATION_TABLE_64_SHIFT (0) + +#define JASPER_CHROMA_QUANTIZATION_TABLE14_OFFSET (0x00C8) + +#define JASPER_CHROMA_QUANTIZATION_TABLE14_CR_CHROMA_QUANTIZATION_TABLE_73_MASK (0xFF000000) +#define JASPER_CHROMA_QUANTIZATION_TABLE14_CR_CHROMA_QUANTIZATION_TABLE_73_SHIFT (24) + +#define JASPER_CHROMA_QUANTIZATION_TABLE14_CR_CHROMA_QUANTIZATION_TABLE_72_MASK (0x00FF0000) +#define JASPER_CHROMA_QUANTIZATION_TABLE14_CR_CHROMA_QUANTIZATION_TABLE_72_SHIFT (16) + +#define JASPER_CHROMA_QUANTIZATION_TABLE14_CR_CHROMA_QUANTIZATION_TABLE_71_MASK (0x0000FF00) +#define JASPER_CHROMA_QUANTIZATION_TABLE14_CR_CHROMA_QUANTIZATION_TABLE_71_SHIFT (8) + +#define JASPER_CHROMA_QUANTIZATION_TABLE14_CR_CHROMA_QUANTIZATION_TABLE_70_MASK (0x000000FF) +#define JASPER_CHROMA_QUANTIZATION_TABLE14_CR_CHROMA_QUANTIZATION_TABLE_70_SHIFT (0) + +#define JASPER_CHROMA_QUANTIZATION_TABLE15_OFFSET (0x00CC) + +#define JASPER_CHROMA_QUANTIZATION_TABLE15_CR_CHROMA_QUANTIZATION_TABLE_77_MASK (0xFF000000) +#define JASPER_CHROMA_QUANTIZATION_TABLE15_CR_CHROMA_QUANTIZATION_TABLE_77_SHIFT (24) + +#define JASPER_CHROMA_QUANTIZATION_TABLE15_CR_CHROMA_QUANTIZATION_TABLE_76_MASK (0x00FF0000) +#define JASPER_CHROMA_QUANTIZATION_TABLE15_CR_CHROMA_QUANTIZATION_TABLE_76_SHIFT (16) + +#define JASPER_CHROMA_QUANTIZATION_TABLE15_CR_CHROMA_QUANTIZATION_TABLE_75_MASK (0x0000FF00) +#define JASPER_CHROMA_QUANTIZATION_TABLE15_CR_CHROMA_QUANTIZATION_TABLE_75_SHIFT (8) + +#define JASPER_CHROMA_QUANTIZATION_TABLE15_CR_CHROMA_QUANTIZATION_TABLE_74_MASK (0x000000FF) +#define JASPER_CHROMA_QUANTIZATION_TABLE15_CR_CHROMA_QUANTIZATION_TABLE_74_SHIFT (0) + +#define JASPER_CRC_CTRL_OFFSET (0x00D0) +#define JASPER_CRC_CTRL_JASPER_CRC_ENABLE_MASK (0x00000001) +#define JASPER_CRC_CTRL_JASPER_CRC_ENABLE_SHIFT (0) + +#define JASPER_FRONT_END_CRC_OFFSET (0x00D4) +#define JASPER_FRONT_END_CRC_CR_JASPER_FRONT_END_CRC_OUT_MASK (0xFFFFFFFF) +#define JASPER_FRONT_END_CRC_CR_JASPER_FRONT_END_CRC_OUT_SHIFT (0) + +#define JASPER_DCT_CRC_OFFSET (0x00D8) +#define JASPER_DCT_CRC_CR_JASPER_DCT_CRC_OUT_MASK (0xFFFFFFFF) +#define JASPER_DCT_CRC_CR_JASPER_DCT_CRC_OUT_SHIFT (0) + +#define JASPER_ZZ_CRC_OFFSET (0x00DC) +#define JASPER_ZZ_CRC_CR_JASPER_ZZ_CRC_OUT_MASK (0xFFFFFFFF) +#define JASPER_ZZ_CRC_CR_JASPER_ZZ_CRC_OUT_SHIFT (0) + +#define JASPER_QUANT_CRC_OFFSET (0x00E0) +#define JASPER_QUANT_CRC_CR_JASPER_QUANT_CRC_OUT_MASK (0xFFFFFFFF) +#define JASPER_QUANT_CRC_CR_JASPER_QUANT_CRC_OUT_SHIFT (0) + +#define JASPER_ENTROPY_ENCODER_CRC_OFFSET (0x00E4) +#define JASPER_ENTROPY_ENCODER_CRC_CR_JASPER_ENTROPY_CRC_OUT_MASK (0xFFFFFFFF) +#define JASPER_ENTROPY_ENCODER_CRC_CR_JASPER_ENTROPY_CRC_OUT_SHIFT (0) + +#define JASPER_PACKING_BUFFER_DATA_CRC_OFFSET (0x00E8) +#define JASPER_PACKING_BUFFER_DATA_CRC_CR_JASPER_PACKING_DATA_CRC_OUT_MASK (0xFFFFFFFF) +#define JASPER_PACKING_BUFFER_DATA_CRC_CR_JASPER_PACKING_DATA_CRC_OUT_SHIFT (0) + +#define JASPER_PACKING_BUFFER_ADDR_CRC_OFFSET (0x00EC) +#define JASPER_PACKING_BUFFER_ADDR_CRC_CR_JASPER_PACKING_ADDR_OUT_CRC_MASK (0xFFFFFFFF) +#define JASPER_PACKING_BUFFER_ADDR_CRC_CR_JASPER_PACKING_ADDR_OUT_CRC_SHIFT (0) + +#define JASPER_CORE_BYTE_SIZE (0x00F0) + +#endif diff --git a/drivers/media/platform/imagination/e5010-jpeg-enc-hw.c b/drivers/media/platform/imagination/e5010-jpeg-enc-hw.c new file mode 100644 index 000000000000..56d5941020fa --- /dev/null +++ b/drivers/media/platform/imagination/e5010-jpeg-enc-hw.c @@ -0,0 +1,267 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Imagination E5010 JPEG Encoder driver. + * + * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/ + * + * Author: David Huang + * Author: Devarsh Thakkar + */ + +#include +#include +#include +#include "e5010-jpeg-enc-hw.h" + +static void write_reg_field(void __iomem *base, unsigned int offset, u32 mask, + unsigned int shift, u32 value) +{ + u32 reg; + + value <<= shift; + if (mask != 0xffffffff) { + reg = readl(base + offset); + value = (value & mask) | (reg & ~mask); + } + writel(value, (base + offset)); +} + +static int write_reg_field_not_busy(void __iomem *jasper_base, void __iomem *wr_base, + unsigned int offset, u32 mask, unsigned int shift, + u32 value) +{ + int ret; + u32 val; + + ret = readl_poll_timeout_atomic(jasper_base + JASPER_STATUS_OFFSET, val, + (val & JASPER_STATUS_CR_JASPER_BUSY_MASK) == 0, + 2000, 50000); + if (ret) + return ret; + + write_reg_field(wr_base, offset, mask, shift, value); + + return 0; +} + +void e5010_reset(struct device *dev, void __iomem *core_base, void __iomem *mmu_base) +{ + int ret = 0; + u32 val; + + write_reg_field(core_base, JASPER_RESET_OFFSET, + JASPER_RESET_CR_CORE_RESET_MASK, + JASPER_RESET_CR_CORE_RESET_SHIFT, 1); + + write_reg_field(mmu_base, MMU_MMU_CONTROL1_OFFSET, + MMU_MMU_CONTROL1_MMU_SOFT_RESET_MASK, + MMU_MMU_CONTROL1_MMU_SOFT_RESET_SHIFT, 1); + + ret = readl_poll_timeout_atomic(mmu_base + MMU_MMU_CONTROL1_OFFSET, val, + (val & MMU_MMU_CONTROL1_MMU_SOFT_RESET_MASK) == 0, + 2000, 50000); + if (ret) + dev_warn(dev, "MMU soft reset timed out, forcing system soft reset\n"); + + write_reg_field(core_base, JASPER_RESET_OFFSET, + JASPER_RESET_CR_SYS_RESET_MASK, + JASPER_RESET_CR_SYS_RESET_SHIFT, 1); +} + +void e5010_hw_bypass_mmu(void __iomem *mmu_base, u32 enable) +{ + /* Bypass MMU */ + write_reg_field(mmu_base, + MMU_MMU_ADDRESS_CONTROL_OFFSET, + MMU_MMU_ADDRESS_CONTROL_MMU_BYPASS_MASK, + MMU_MMU_ADDRESS_CONTROL_MMU_BYPASS_SHIFT, + enable); +} + +int e5010_hw_enable_output_address_error_irq(void __iomem *core_base, u32 enable) +{ + return write_reg_field_not_busy(core_base, core_base, + JASPER_INTERRUPT_MASK_OFFSET, + JASPER_INTERRUPT_MASK_CR_OUTPUT_ADDRESS_ERROR_ENABLE_MASK, + JASPER_INTERRUPT_MASK_CR_OUTPUT_ADDRESS_ERROR_ENABLE_SHIFT, + enable); +} + +bool e5010_hw_pic_done_irq(void __iomem *core_base) +{ + u32 reg; + + reg = readl(core_base + JASPER_INTERRUPT_STATUS_OFFSET); + return reg & JASPER_INTERRUPT_STATUS_CR_PICTURE_DONE_IRQ_MASK; +} + +bool e5010_hw_output_address_irq(void __iomem *core_base) +{ + u32 reg; + + reg = readl(core_base + JASPER_INTERRUPT_STATUS_OFFSET); + return reg & JASPER_INTERRUPT_STATUS_CR_OUTPUT_ADDRESS_ERROR_IRQ_MASK; +} + +int e5010_hw_enable_picture_done_irq(void __iomem *core_base, u32 enable) +{ + return write_reg_field_not_busy(core_base, core_base, + JASPER_INTERRUPT_MASK_OFFSET, + JASPER_INTERRUPT_MASK_CR_PICTURE_DONE_ENABLE_MASK, + JASPER_INTERRUPT_MASK_CR_PICTURE_DONE_ENABLE_SHIFT, + enable); +} + +int e5010_hw_enable_auto_clock_gating(void __iomem *core_base, u32 enable) +{ + return write_reg_field_not_busy(core_base, core_base, + JASPER_CLK_CONTROL_OFFSET, + JASPER_CLK_CONTROL_CR_JASPER_AUTO_CLKG_ENABLE_MASK, + JASPER_CLK_CONTROL_CR_JASPER_AUTO_CLKG_ENABLE_SHIFT, + enable); +} + +int e5010_hw_enable_manual_clock_gating(void __iomem *core_base, u32 enable) +{ + return write_reg_field_not_busy(core_base, core_base, + JASPER_CLK_CONTROL_OFFSET, + JASPER_CLK_CONTROL_CR_JASPER_MAN_CLKG_ENABLE_MASK, + JASPER_CLK_CONTROL_CR_JASPER_MAN_CLKG_ENABLE_SHIFT, 0); +} + +int e5010_hw_enable_crc_check(void __iomem *core_base, u32 enable) +{ + return write_reg_field_not_busy(core_base, core_base, + JASPER_CRC_CTRL_OFFSET, + JASPER_CRC_CTRL_JASPER_CRC_ENABLE_MASK, + JASPER_CRC_CTRL_JASPER_CRC_ENABLE_SHIFT, enable); +} + +int e5010_hw_set_input_source_to_memory(void __iomem *core_base, u32 set) +{ + return write_reg_field_not_busy(core_base, core_base, + JASPER_INPUT_CTRL0_OFFSET, + JASPER_INPUT_CTRL0_CR_INPUT_SOURCE_MASK, + JASPER_INPUT_CTRL0_CR_INPUT_SOURCE_SHIFT, set); +} + +int e5010_hw_set_input_luma_addr(void __iomem *core_base, u32 val) +{ + return write_reg_field_not_busy(core_base, core_base, + INPUT_LUMA_BASE_OFFSET, + INPUT_LUMA_BASE_CR_INPUT_LUMA_BASE_MASK, 0, val); +} + +int e5010_hw_set_input_chroma_addr(void __iomem *core_base, u32 val) +{ + return write_reg_field_not_busy(core_base, core_base, + INPUT_CHROMA_BASE_OFFSET, + INPUT_CHROMA_BASE_CR_INPUT_CHROMA_BASE_MASK, 0, val); +} + +int e5010_hw_set_output_base_addr(void __iomem *core_base, u32 val) +{ + return write_reg_field_not_busy(core_base, core_base, + JASPER_OUTPUT_BASE_OFFSET, + JASPER_OUTPUT_BASE_CR_OUTPUT_BASE_MASK, + JASPER_OUTPUT_BASE_CR_OUTPUT_BASE_SHIFT, val); +} + +int e5010_hw_set_horizontal_size(void __iomem *core_base, u32 val) +{ + return write_reg_field_not_busy(core_base, core_base, + JASPER_IMAGE_SIZE_OFFSET, + JASPER_IMAGE_SIZE_CR_IMAGE_HORIZONTAL_SIZE_MASK, + JASPER_IMAGE_SIZE_CR_IMAGE_HORIZONTAL_SIZE_SHIFT, + val); +} + +int e5010_hw_set_vertical_size(void __iomem *core_base, u32 val) +{ + return write_reg_field_not_busy(core_base, core_base, + JASPER_IMAGE_SIZE_OFFSET, + JASPER_IMAGE_SIZE_CR_IMAGE_VERTICAL_SIZE_MASK, + JASPER_IMAGE_SIZE_CR_IMAGE_VERTICAL_SIZE_SHIFT, + val); +} + +int e5010_hw_set_luma_stride(void __iomem *core_base, u32 bytesperline) +{ + u32 val = bytesperline / 64; + + return write_reg_field_not_busy(core_base, core_base, + JASPER_INPUT_CTRL1_OFFSET, + JASPER_INPUT_CTRL1_CR_INPUT_LUMA_STRIDE_MASK, + JASPER_INPUT_CTRL1_CR_INPUT_LUMA_STRIDE_SHIFT, + val); +} + +int e5010_hw_set_chroma_stride(void __iomem *core_base, u32 bytesperline) +{ + u32 val = bytesperline / 64; + + return write_reg_field_not_busy(core_base, core_base, + JASPER_INPUT_CTRL1_OFFSET, + JASPER_INPUT_CTRL1_CR_INPUT_CHROMA_STRIDE_MASK, + JASPER_INPUT_CTRL1_CR_INPUT_CHROMA_STRIDE_SHIFT, + val); +} + +int e5010_hw_set_input_subsampling(void __iomem *core_base, u32 val) +{ + return write_reg_field_not_busy(core_base, core_base, + JASPER_INPUT_CTRL0_OFFSET, + JASPER_INPUT_CTRL0_CR_INPUT_SUBSAMPLING_MASK, + JASPER_INPUT_CTRL0_CR_INPUT_SUBSAMPLING_SHIFT, + val); +} + +int e5010_hw_set_chroma_order(void __iomem *core_base, u32 val) +{ + return write_reg_field_not_busy(core_base, core_base, + JASPER_INPUT_CTRL0_OFFSET, + JASPER_INPUT_CTRL0_CR_INPUT_CHROMA_ORDER_MASK, + JASPER_INPUT_CTRL0_CR_INPUT_CHROMA_ORDER_SHIFT, + val); +} + +void e5010_hw_set_output_max_size(void __iomem *core_base, u32 val) +{ + write_reg_field(core_base, JASPER_OUTPUT_MAX_SIZE_OFFSET, + JASPER_OUTPUT_MAX_SIZE_CR_OUTPUT_MAX_SIZE_MASK, + JASPER_OUTPUT_MAX_SIZE_CR_OUTPUT_MAX_SIZE_SHIFT, + val); +} + +int e5010_hw_set_qpvalue(void __iomem *core_base, u32 offset, u32 val) +{ + return write_reg_field_not_busy(core_base, core_base, offset, 0xffffffff, 0, val); +} + +void e5010_hw_clear_output_error(void __iomem *core_base, u32 clear) +{ + /* Make sure interrupts are clear */ + write_reg_field(core_base, JASPER_INTERRUPT_CLEAR_OFFSET, + JASPER_INTERRUPT_CLEAR_CR_OUTPUT_ERROR_CLEAR_MASK, + JASPER_INTERRUPT_CLEAR_CR_OUTPUT_ERROR_CLEAR_SHIFT, clear); +} + +void e5010_hw_clear_picture_done(void __iomem *core_base, u32 clear) +{ + write_reg_field(core_base, + JASPER_INTERRUPT_CLEAR_OFFSET, + JASPER_INTERRUPT_CLEAR_CR_PICTURE_DONE_CLEAR_MASK, + JASPER_INTERRUPT_CLEAR_CR_PICTURE_DONE_CLEAR_SHIFT, clear); +} + +int e5010_hw_get_output_size(void __iomem *core_base) +{ + return readl(core_base + JASPER_OUTPUT_SIZE_OFFSET); +} + +void e5010_hw_encode_start(void __iomem *core_base, u32 start) +{ + write_reg_field(core_base, JASPER_CORE_CTRL_OFFSET, + JASPER_CORE_CTRL_CR_JASPER_ENCODE_START_MASK, + JASPER_CORE_CTRL_CR_JASPER_ENCODE_START_SHIFT, start); +} diff --git a/drivers/media/platform/imagination/e5010-jpeg-enc-hw.h b/drivers/media/platform/imagination/e5010-jpeg-enc-hw.h new file mode 100644 index 000000000000..781d353c3226 --- /dev/null +++ b/drivers/media/platform/imagination/e5010-jpeg-enc-hw.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Imagination E5010 JPEG Encoder driver. + * + * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/ + * + * Author: David Huang + * Author: Devarsh Thakkar + */ + +#ifndef _E5010_JPEG_ENC_HW_H +#define _E5010_JPEG_ENC_HW_H + +#include "e5010-core-regs.h" +#include "e5010-mmu-regs.h" + +int e5010_hw_enable_output_address_error_irq(void __iomem *core_offset, u32 enable); +int e5010_hw_enable_picture_done_irq(void __iomem *core_offset, u32 enable); +int e5010_hw_enable_auto_clock_gating(void __iomem *core_offset, u32 enable); +int e5010_hw_enable_manual_clock_gating(void __iomem *core_offset, u32 enable); +int e5010_hw_enable_crc_check(void __iomem *core_offset, u32 enable); +int e5010_hw_set_input_source_to_memory(void __iomem *core_offset, u32 set); +int e5010_hw_set_input_luma_addr(void __iomem *core_offset, u32 val); +int e5010_hw_set_input_chroma_addr(void __iomem *core_offset, u32 val); +int e5010_hw_set_output_base_addr(void __iomem *core_offset, u32 val); +int e5010_hw_get_output_size(void __iomem *core_offset); +int e5010_hw_set_horizontal_size(void __iomem *core_offset, u32 val); +int e5010_hw_set_vertical_size(void __iomem *core_offset, u32 val); +int e5010_hw_set_luma_stride(void __iomem *core_offset, u32 bytesperline); +int e5010_hw_set_chroma_stride(void __iomem *core_offset, u32 bytesperline); +int e5010_hw_set_input_subsampling(void __iomem *core_offset, u32 val); +int e5010_hw_set_chroma_order(void __iomem *core_offset, u32 val); +int e5010_hw_set_qpvalue(void __iomem *core_offset, u32 offset, u32 value); +void e5010_reset(struct device *dev, void __iomem *core_offset, void __iomem *mmu_offset); +void e5010_hw_set_output_max_size(void __iomem *core_offset, u32 val); +void e5010_hw_clear_picture_done(void __iomem *core_offset, u32 clear); +void e5010_hw_encode_start(void __iomem *core_offset, u32 start); +void e5010_hw_clear_output_error(void __iomem *core_offset, u32 clear); +void e5010_hw_bypass_mmu(void __iomem *mmu_base, u32 enable); +bool e5010_hw_pic_done_irq(void __iomem *core_base); +bool e5010_hw_output_address_irq(void __iomem *core_base); +#endif diff --git a/drivers/media/platform/imagination/e5010-jpeg-enc.c b/drivers/media/platform/imagination/e5010-jpeg-enc.c new file mode 100644 index 000000000000..17b8ec306ffc --- /dev/null +++ b/drivers/media/platform/imagination/e5010-jpeg-enc.c @@ -0,0 +1,1743 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Imagination E5010 JPEG Encoder driver. + * + * TODO: Add MMU and memory tiling support + * + * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/ + * + * Author: David Huang + * Author: Devarsh Thakkar + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "e5010-jpeg-enc.h" +#include "e5010-jpeg-enc-hw.h" + +/* Luma and chroma qp table to achieve 50% compression quality + * This is as per example in Annex K.1 of ITU-T.81 + */ +static const u8 luma_q_table[64] = { + 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 56, 68, 109, 103, 77, + 24, 35, 55, 64, 81, 104, 113, 92, + 49, 64, 78, 87, 103, 121, 120, 101, + 72, 92, 95, 98, 112, 100, 103, 99 +}; + +static const u8 chroma_q_table[64] = { + 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 +}; + +/* Zigzag scan pattern */ +static const u8 zigzag[64] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63 +}; + +/* + * Contains the data that needs to be sent in the marker segment of an interchange format JPEG + * stream or an abbreviated format table specification data stream. + * Specifies the huffman table used for encoding the luminance DC coefficient differences. + * The table represents Table K.3 of ITU-T.81 + */ +static const u8 luma_dc_table[] = { + 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B +}; + +/* + * Contains the data that needs to be sent in the marker segment of an interchange format JPEG + * stream or an abbreviated format table specification data stream. + * Specifies the huffman table used for encoding the luminance AC coefficients. + * The table represents Table K.5 of ITU-T.81 + */ +static const u8 luma_ac_table[] = { + 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, + 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, + 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, + 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, + 0xD1, 0xF0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25, + 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, + 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, + 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x83, + 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, + 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, + 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, + 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, + 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA +}; + +/* + * Contains the data that needs to be sent in the marker segment of an interchange format JPEG + * stream or an abbreviated format table specification data stream. + * Specifies the huffman table used for encoding the chrominance DC coefficient differences. + * The table represents Table K.4 of ITU-T.81 + */ +static const u8 chroma_dc_table[] = { + 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B +}; + +/* + * Contains the data that needs to be sent in the marker segment of an interchange format JPEG + * stream or an abbreviated format table specification data stream. + * Specifies the huffman table used for encoding the chrominance AC coefficients. + * The table represents Table K.6 of ITU-T.81 + */ +static const u8 chroma_ac_table[] = { + 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, + 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, + 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, + 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, + 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, + 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, + 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, + 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, + 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, + 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, + 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, + 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA +}; + +#define JPEG_LUM_HT 0x00 +#define JPEG_CHR_HT 0x01 +#define JPEG_DC_HT 0x00 +#define JPEG_AC_HT 0x10 + +/* forward declarations */ +static const struct of_device_id e5010_of_match[]; + +static const struct v4l2_file_operations e5010_fops; + +static const struct v4l2_ioctl_ops e5010_ioctl_ops; + +static const struct vb2_ops e5010_video_ops; + +static const struct v4l2_m2m_ops e5010_m2m_ops; + +static struct e5010_fmt e5010_formats[] = { + { + .fourcc = V4L2_PIX_FMT_NV12, + .num_planes = 1, + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420, + .chroma_order = CHROMA_ORDER_CB_CR, + .frmsize = { MIN_DIMENSION, MAX_DIMENSION, 64, + MIN_DIMENSION, MAX_DIMENSION, 8 }, + }, + { + .fourcc = V4L2_PIX_FMT_NV12M, + .num_planes = 2, + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420, + .chroma_order = CHROMA_ORDER_CB_CR, + .frmsize = { MIN_DIMENSION, MAX_DIMENSION, 64, + MIN_DIMENSION, MAX_DIMENSION, 8 }, + }, + { + .fourcc = V4L2_PIX_FMT_NV21, + .num_planes = 1, + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420, + .chroma_order = CHROMA_ORDER_CR_CB, + .frmsize = { MIN_DIMENSION, MAX_DIMENSION, 64, + MIN_DIMENSION, MAX_DIMENSION, 8 }, + }, + { + .fourcc = V4L2_PIX_FMT_NV21M, + .num_planes = 2, + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420, + .chroma_order = CHROMA_ORDER_CR_CB, + .frmsize = { MIN_DIMENSION, MAX_DIMENSION, 64, + MIN_DIMENSION, MAX_DIMENSION, 8 }, + }, + { + .fourcc = V4L2_PIX_FMT_NV16, + .num_planes = 1, + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422, + .chroma_order = CHROMA_ORDER_CB_CR, + .frmsize = { MIN_DIMENSION, MAX_DIMENSION, 64, + MIN_DIMENSION, MAX_DIMENSION, 8 }, + }, + { + .fourcc = V4L2_PIX_FMT_NV16M, + .num_planes = 2, + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422, + .chroma_order = CHROMA_ORDER_CB_CR, + .frmsize = { MIN_DIMENSION, MAX_DIMENSION, 64, + MIN_DIMENSION, MAX_DIMENSION, 8 }, + + }, + { + .fourcc = V4L2_PIX_FMT_NV61, + .num_planes = 1, + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422, + .chroma_order = CHROMA_ORDER_CR_CB, + .frmsize = { MIN_DIMENSION, MAX_DIMENSION, 64, + MIN_DIMENSION, MAX_DIMENSION, 8 }, + }, + { + .fourcc = V4L2_PIX_FMT_NV61M, + .num_planes = 2, + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422, + .chroma_order = CHROMA_ORDER_CR_CB, + .frmsize = { MIN_DIMENSION, MAX_DIMENSION, 64, + MIN_DIMENSION, MAX_DIMENSION, 8 }, + }, + { + .fourcc = V4L2_PIX_FMT_JPEG, + .num_planes = 1, + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, + .subsampling = 0, + .chroma_order = 0, + .frmsize = { MIN_DIMENSION, MAX_DIMENSION, 16, + MIN_DIMENSION, MAX_DIMENSION, 8 }, + }, +}; + +static unsigned int debug; +module_param(debug, uint, 0644); +MODULE_PARM_DESC(debug, "debug level"); + +#define dprintk(dev, lvl, fmt, arg...) \ + v4l2_dbg(lvl, debug, &(dev)->v4l2_dev, "%s: " fmt, __func__, ## arg) + +static const struct v4l2_event e5010_eos_event = { + .type = V4L2_EVENT_EOS +}; + +static const char *type_name(enum v4l2_buf_type type) +{ + switch (type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + return "Output"; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + return "Capture"; + default: + return "Invalid"; + } +} + +static struct e5010_q_data *get_queue(struct e5010_context *ctx, enum v4l2_buf_type type) +{ + return (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ? &ctx->out_queue : &ctx->cap_queue; +} + +static void calculate_qp_tables(struct e5010_context *ctx) +{ + long long luminosity, contrast; + int quality, i; + + quality = 50 - ctx->quality; + + luminosity = LUMINOSITY * quality / 50; + contrast = CONTRAST * quality / 50; + + if (quality > 0) { + luminosity *= INCREASE; + contrast *= INCREASE; + } + + for (i = 0; i < ARRAY_SIZE(luma_q_table); i++) { + long long delta = chroma_q_table[i] * contrast + luminosity; + int val = (int)(chroma_q_table[i] + delta); + + clamp(val, 1, 255); + ctx->chroma_qp[i] = quality == -50 ? 1 : val; + + delta = luma_q_table[i] * contrast + luminosity; + val = (int)(luma_q_table[i] + delta); + clamp(val, 1, 255); + ctx->luma_qp[i] = quality == -50 ? 1 : val; + } + + ctx->update_qp = true; +} + +static int update_qp_tables(struct e5010_context *ctx) +{ + struct e5010_dev *e5010 = ctx->e5010; + int i, ret = 0; + u32 lvalue, cvalue; + + lvalue = 0; + cvalue = 0; + + for (i = 0; i < QP_TABLE_SIZE; i++) { + lvalue |= ctx->luma_qp[i] << (8 * (i % 4)); + cvalue |= ctx->chroma_qp[i] << (8 * (i % 4)); + if (i % 4 == 3) { + ret |= e5010_hw_set_qpvalue(e5010->core_base, + JASPER_LUMA_QUANTIZATION_TABLE0_OFFSET + + QP_TABLE_FIELD_OFFSET * ((i - 3) / 4), + lvalue); + ret |= e5010_hw_set_qpvalue(e5010->core_base, + JASPER_CHROMA_QUANTIZATION_TABLE0_OFFSET + + QP_TABLE_FIELD_OFFSET * ((i - 3) / 4), + cvalue); + lvalue = 0; + cvalue = 0; + } + } + + return ret; +} + +static int e5010_set_input_subsampling(void __iomem *core_base, int subsampling) +{ + switch (subsampling) { + case V4L2_JPEG_CHROMA_SUBSAMPLING_420: + return e5010_hw_set_input_subsampling(core_base, SUBSAMPLING_420); + case V4L2_JPEG_CHROMA_SUBSAMPLING_422: + return e5010_hw_set_input_subsampling(core_base, SUBSAMPLING_422); + default: + return -EINVAL; + }; +} + +static int e5010_querycap(struct file *file, void *priv, struct v4l2_capability *cap) +{ + strscpy(cap->driver, E5010_MODULE_NAME, sizeof(cap->driver)); + strscpy(cap->card, E5010_MODULE_NAME, sizeof(cap->card)); + + return 0; +} + +static struct e5010_fmt *find_format(struct v4l2_format *f) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(e5010_formats); ++i) { + if (e5010_formats[i].fourcc == f->fmt.pix_mp.pixelformat && + e5010_formats[i].type == f->type) + return &e5010_formats[i]; + } + + return NULL; +} + +static int e5010_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f) +{ + int i, index = 0; + struct e5010_fmt *fmt = NULL; + struct e5010_context *ctx = file->private_data; + + if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) { + v4l2_err(&ctx->e5010->v4l2_dev, "ENUMFMT with Invalid type: %d\n", f->type); + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(e5010_formats); ++i) { + if (e5010_formats[i].type == f->type) { + if (index == f->index) { + fmt = &e5010_formats[i]; + break; + } + index++; + } + } + + if (!fmt) + return -EINVAL; + + f->pixelformat = fmt->fourcc; + return 0; +} + +static int e5010_g_fmt(struct file *file, void *priv, struct v4l2_format *f) +{ + struct e5010_context *ctx = file->private_data; + struct e5010_q_data *queue; + int i; + struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; + struct v4l2_plane_pix_format *plane_fmt = pix_mp->plane_fmt; + + queue = get_queue(ctx, f->type); + + pix_mp->flags = 0; + pix_mp->field = V4L2_FIELD_NONE; + pix_mp->pixelformat = queue->fmt->fourcc; + pix_mp->width = queue->width_adjusted; + pix_mp->height = queue->height_adjusted; + pix_mp->num_planes = queue->fmt->num_planes; + + if (V4L2_TYPE_IS_OUTPUT(f->type)) { + if (!pix_mp->colorspace) + pix_mp->colorspace = V4L2_COLORSPACE_SRGB; + + for (i = 0; i < queue->fmt->num_planes; i++) { + plane_fmt[i].sizeimage = queue->sizeimage[i]; + plane_fmt[i].bytesperline = queue->bytesperline[i]; + } + + } else { + pix_mp->colorspace = V4L2_COLORSPACE_JPEG; + plane_fmt[0].bytesperline = 0; + plane_fmt[0].sizeimage = queue->sizeimage[0]; + } + pix_mp->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; + pix_mp->xfer_func = V4L2_XFER_FUNC_DEFAULT; + pix_mp->quantization = V4L2_QUANTIZATION_DEFAULT; + + return 0; +} + +static int e5010_jpeg_try_fmt(struct v4l2_format *f, struct e5010_context *ctx) +{ + struct e5010_fmt *fmt; + struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; + struct v4l2_plane_pix_format *plane_fmt = pix_mp->plane_fmt; + + fmt = find_format(f); + if (!fmt) { + if (V4L2_TYPE_IS_OUTPUT(f->type)) + pix_mp->pixelformat = V4L2_PIX_FMT_NV12; + else + pix_mp->pixelformat = V4L2_PIX_FMT_JPEG; + fmt = find_format(f); + if (!fmt) + return -EINVAL; + } + + if (V4L2_TYPE_IS_OUTPUT(f->type)) { + if (!pix_mp->colorspace) + pix_mp->colorspace = V4L2_COLORSPACE_JPEG; + if (!pix_mp->ycbcr_enc) + pix_mp->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; + if (!pix_mp->quantization) + pix_mp->quantization = V4L2_QUANTIZATION_DEFAULT; + if (!pix_mp->xfer_func) + pix_mp->xfer_func = V4L2_XFER_FUNC_DEFAULT; + + v4l2_apply_frmsize_constraints(&pix_mp->width, + &pix_mp->height, + &fmt->frmsize); + + v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat, + pix_mp->width, pix_mp->height); + + } else { + pix_mp->colorspace = V4L2_COLORSPACE_JPEG; + pix_mp->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; + pix_mp->quantization = V4L2_QUANTIZATION_DEFAULT; + pix_mp->xfer_func = V4L2_XFER_FUNC_DEFAULT; + v4l2_apply_frmsize_constraints(&pix_mp->width, + &pix_mp->height, + &fmt->frmsize); + plane_fmt[0].sizeimage = pix_mp->width * pix_mp->height * JPEG_MAX_BYTES_PER_PIXEL; + plane_fmt[0].sizeimage += HEADER_SIZE; + plane_fmt[0].bytesperline = 0; + pix_mp->pixelformat = fmt->fourcc; + pix_mp->num_planes = fmt->num_planes; + } + pix_mp->flags = 0; + pix_mp->field = V4L2_FIELD_NONE; + + dprintk(ctx->e5010, 2, + "ctx: 0x%p: format type %s:, wxh: %dx%d (plane0 : %d bytes, plane1 : %d bytes),fmt: %c%c%c%c\n", + ctx, type_name(f->type), pix_mp->width, pix_mp->height, + plane_fmt[0].sizeimage, plane_fmt[1].sizeimage, + (fmt->fourcc & 0xff), + (fmt->fourcc >> 8) & 0xff, + (fmt->fourcc >> 16) & 0xff, + (fmt->fourcc >> 24) & 0xff); + + return 0; +} + +static int e5010_try_fmt(struct file *file, void *priv, struct v4l2_format *f) +{ + struct e5010_context *ctx = file->private_data; + + return e5010_jpeg_try_fmt(f, ctx); +} + +static int e5010_s_fmt(struct file *file, void *priv, struct v4l2_format *f) +{ + struct e5010_context *ctx = file->private_data; + struct vb2_queue *vq; + int ret = 0, i = 0; + struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; + struct v4l2_plane_pix_format *plane_fmt = pix_mp->plane_fmt; + struct e5010_q_data *queue; + struct e5010_fmt *fmt; + + vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); + if (!vq) + return -EINVAL; + + if (vb2_is_busy(vq)) { + v4l2_err(&ctx->e5010->v4l2_dev, "queue busy\n"); + return -EBUSY; + } + + ret = e5010_jpeg_try_fmt(f, ctx); + if (ret) + return ret; + + fmt = find_format(f); + queue = get_queue(ctx, f->type); + + queue->fmt = fmt; + queue->width = pix_mp->width; + queue->height = pix_mp->height; + + if (V4L2_TYPE_IS_OUTPUT(f->type)) { + for (i = 0; i < fmt->num_planes; i++) { + queue->bytesperline[i] = plane_fmt[i].bytesperline; + queue->sizeimage[i] = plane_fmt[i].sizeimage; + } + queue->crop.left = 0; + queue->crop.top = 0; + queue->crop.width = queue->width; + queue->crop.height = queue->height; + } else { + queue->sizeimage[0] = plane_fmt[0].sizeimage; + queue->sizeimage[1] = 0; + queue->bytesperline[0] = 0; + queue->bytesperline[1] = 0; + } + + return 0; +} + +static int e5010_enum_framesizes(struct file *file, void *priv, struct v4l2_frmsizeenum *fsize) +{ + struct v4l2_format f; + struct e5010_fmt *fmt; + + if (fsize->index != 0) + return -EINVAL; + + f.fmt.pix_mp.pixelformat = fsize->pixel_format; + if (f.fmt.pix_mp.pixelformat == V4L2_PIX_FMT_JPEG) + f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + else + f.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + + fmt = find_format(&f); + if (!fmt) + return -EINVAL; + + fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; + fsize->stepwise = fmt->frmsize; + fsize->reserved[0] = 0; + fsize->reserved[1] = 0; + + return 0; +} + +static int e5010_g_selection(struct file *file, void *fh, struct v4l2_selection *s) +{ + struct e5010_context *ctx = file->private_data; + struct e5010_q_data *queue; + + if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) + return -EINVAL; + + queue = get_queue(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + + switch (s->target) { + case V4L2_SEL_TGT_CROP_DEFAULT: + case V4L2_SEL_TGT_CROP_BOUNDS: + s->r.left = 0; + s->r.top = 0; + s->r.width = queue->width; + s->r.height = queue->height; + break; + case V4L2_SEL_TGT_CROP: + memcpy(&s->r, &queue->crop, sizeof(s->r)); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int e5010_s_selection(struct file *file, void *fh, struct v4l2_selection *s) +{ + struct e5010_context *ctx = file->private_data; + struct e5010_q_data *queue; + struct vb2_queue *vq; + struct v4l2_rect base_rect; + + vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, s->type); + if (!vq) + return -EINVAL; + + if (vb2_is_streaming(vq)) + return -EBUSY; + + if (s->target != V4L2_SEL_TGT_CROP || + s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) + return -EINVAL; + + queue = get_queue(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + base_rect.top = 0; + base_rect.left = 0; + base_rect.width = queue->width; + base_rect.height = queue->height; + + switch (s->flags) { + case 0: + s->r.width = round_down(s->r.width, queue->fmt->frmsize.step_width); + s->r.height = round_down(s->r.height, queue->fmt->frmsize.step_height); + s->r.left = round_down(s->r.left, queue->fmt->frmsize.step_width); + s->r.top = round_down(s->r.top, 2); + + if (s->r.left + s->r.width > queue->width) + s->r.width = round_down(s->r.width + s->r.left - queue->width, + queue->fmt->frmsize.step_width); + if (s->r.top + s->r.height > queue->height) + s->r.top = round_down(s->r.top + s->r.height - queue->height, 2); + break; + case V4L2_SEL_FLAG_GE: + s->r.width = round_up(s->r.width, queue->fmt->frmsize.step_width); + s->r.height = round_up(s->r.height, queue->fmt->frmsize.step_height); + s->r.left = round_up(s->r.left, queue->fmt->frmsize.step_width); + s->r.top = round_up(s->r.top, 2); + break; + case V4L2_SEL_FLAG_LE: + s->r.width = round_down(s->r.width, queue->fmt->frmsize.step_width); + s->r.height = round_down(s->r.height, queue->fmt->frmsize.step_height); + s->r.left = round_down(s->r.left, queue->fmt->frmsize.step_width); + s->r.top = round_down(s->r.top, 2); + break; + case V4L2_SEL_FLAG_LE | V4L2_SEL_FLAG_GE: + if (!IS_ALIGNED(s->r.width, queue->fmt->frmsize.step_width) || + !IS_ALIGNED(s->r.height, queue->fmt->frmsize.step_height) || + !IS_ALIGNED(s->r.left, queue->fmt->frmsize.step_width) || + !IS_ALIGNED(s->r.top, 2)) + return -ERANGE; + break; + default: + return -EINVAL; + } + + if (!v4l2_rect_enclosed(&s->r, &base_rect)) + return -ERANGE; + + memcpy(&queue->crop, &s->r, sizeof(s->r)); + + if (!v4l2_rect_equal(&s->r, &base_rect)) + queue->crop_set = true; + + dprintk(ctx->e5010, 2, "ctx: 0x%p: crop rectangle: w: %d, h : %d, l : %d, t : %d\n", + ctx, queue->crop.width, queue->crop.height, queue->crop.left, queue->crop.top); + + return 0; +} + +static int e5010_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub) +{ + switch (sub->type) { + case V4L2_EVENT_EOS: + return v4l2_event_subscribe(fh, sub, 0, NULL); + case V4L2_EVENT_CTRL: + return v4l2_ctrl_subscribe_event(fh, sub); + default: + return -EINVAL; + } + + return 0; +} + +static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq) +{ + struct e5010_context *ctx = priv; + struct e5010_dev *e5010 = ctx->e5010; + int ret = 0; + + /* src_vq */ + memset(src_vq, 0, sizeof(*src_vq)); + src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + src_vq->io_modes = VB2_MMAP | VB2_DMABUF; + src_vq->drv_priv = ctx; + src_vq->buf_struct_size = sizeof(struct e5010_buffer); + src_vq->ops = &e5010_video_ops; + src_vq->mem_ops = &vb2_dma_contig_memops; + src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; + src_vq->lock = &e5010->mutex; + src_vq->dev = e5010->v4l2_dev.dev; + + ret = vb2_queue_init(src_vq); + if (ret) + return ret; + + /* dst_vq */ + memset(dst_vq, 0, sizeof(*dst_vq)); + dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; + dst_vq->drv_priv = ctx; + dst_vq->buf_struct_size = sizeof(struct e5010_buffer); + dst_vq->ops = &e5010_video_ops; + dst_vq->mem_ops = &vb2_dma_contig_memops; + dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; + dst_vq->lock = &e5010->mutex; + dst_vq->dev = e5010->v4l2_dev.dev; + + ret = vb2_queue_init(dst_vq); + if (ret) { + vb2_queue_release(src_vq); + return ret; + } + + return 0; +} + +static int e5010_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct e5010_context *ctx = + container_of(ctrl->handler, struct e5010_context, ctrl_handler); + + switch (ctrl->id) { + case V4L2_CID_JPEG_COMPRESSION_QUALITY: + ctx->quality = ctrl->val; + calculate_qp_tables(ctx); + dprintk(ctx->e5010, 2, "ctx: 0x%p compression quality set to : %d\n", ctx, + ctx->quality); + break; + default: + return -EINVAL; + } + + return 0; +} + +static const struct v4l2_ctrl_ops e5010_ctrl_ops = { + .s_ctrl = e5010_s_ctrl, +}; + +static void e5010_encode_ctrls(struct e5010_context *ctx) +{ + v4l2_ctrl_new_std(&ctx->ctrl_handler, &e5010_ctrl_ops, + V4L2_CID_JPEG_COMPRESSION_QUALITY, 1, 100, 1, 75); +} + +static int e5010_ctrls_setup(struct e5010_context *ctx) +{ + int err; + + v4l2_ctrl_handler_init(&ctx->ctrl_handler, 1); + + e5010_encode_ctrls(ctx); + + if (ctx->ctrl_handler.error) { + err = ctx->ctrl_handler.error; + v4l2_ctrl_handler_free(&ctx->ctrl_handler); + + return err; + } + + err = v4l2_ctrl_handler_setup(&ctx->ctrl_handler); + if (err) + v4l2_ctrl_handler_free(&ctx->ctrl_handler); + + return err; +} + +static void e5010_jpeg_set_default_params(struct e5010_context *ctx) +{ + struct e5010_q_data *queue; + struct v4l2_format f; + struct e5010_fmt *fmt; + struct v4l2_pix_format_mplane *pix_mp = &f.fmt.pix_mp; + struct v4l2_plane_pix_format *plane_fmt = pix_mp->plane_fmt; + int i = 0; + + f.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12; + fmt = find_format(&f); + queue = &ctx->out_queue; + queue->fmt = fmt; + queue->width = DEFAULT_WIDTH; + queue->height = DEFAULT_HEIGHT; + pix_mp->width = queue->width; + pix_mp->height = queue->height; + queue->crop.left = 0; + queue->crop.top = 0; + queue->crop.width = queue->width; + queue->crop.height = queue->height; + v4l2_apply_frmsize_constraints(&pix_mp->width, + &pix_mp->height, + &fmt->frmsize); + v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat, + pix_mp->width, pix_mp->height); + for (i = 0; i < fmt->num_planes; i++) { + queue->bytesperline[i] = plane_fmt[i].bytesperline; + queue->sizeimage[i] = plane_fmt[i].sizeimage; + } + queue->width_adjusted = pix_mp->width; + queue->height_adjusted = pix_mp->height; + + f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_JPEG; + fmt = find_format(&f); + queue = &ctx->cap_queue; + queue->fmt = fmt; + queue->width = DEFAULT_WIDTH; + queue->height = DEFAULT_HEIGHT; + pix_mp->width = queue->width; + pix_mp->height = queue->height; + v4l2_apply_frmsize_constraints(&pix_mp->width, + &pix_mp->height, + &fmt->frmsize); + queue->sizeimage[0] = pix_mp->width * pix_mp->height * JPEG_MAX_BYTES_PER_PIXEL; + queue->sizeimage[0] += HEADER_SIZE; + queue->sizeimage[1] = 0; + queue->bytesperline[0] = 0; + queue->bytesperline[1] = 0; + queue->width_adjusted = pix_mp->width; + queue->height_adjusted = pix_mp->height; +} + +static int e5010_open(struct file *file) +{ + struct e5010_dev *e5010 = video_drvdata(file); + struct video_device *vdev = video_devdata(file); + struct e5010_context *ctx; + int ret = 0; + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + if (mutex_lock_interruptible(&e5010->mutex)) { + ret = -ERESTARTSYS; + goto free; + } + + v4l2_fh_init(&ctx->fh, vdev); + file->private_data = ctx; + v4l2_fh_add(&ctx->fh); + + ctx->e5010 = e5010; + ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(e5010->m2m_dev, ctx, queue_init); + if (IS_ERR(ctx->fh.m2m_ctx)) { + v4l2_err(&e5010->v4l2_dev, "failed to init m2m ctx\n"); + ret = PTR_ERR(ctx->fh.m2m_ctx); + goto exit; + } + + ret = e5010_ctrls_setup(ctx); + if (ret) { + v4l2_err(&e5010->v4l2_dev, "failed to setup e5010 jpeg controls\n"); + goto err_ctrls_setup; + } + ctx->fh.ctrl_handler = &ctx->ctrl_handler; + + e5010_jpeg_set_default_params(ctx); + + dprintk(e5010, 1, "Created instance: 0x%p, m2m_ctx: 0x%p\n", ctx, ctx->fh.m2m_ctx); + + mutex_unlock(&e5010->mutex); + return 0; + +err_ctrls_setup: + v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); +exit: + v4l2_fh_del(&ctx->fh); + v4l2_fh_exit(&ctx->fh); + mutex_unlock(&e5010->mutex); +free: + kfree(ctx); + return ret; +} + +static int e5010_release(struct file *file) +{ + struct e5010_dev *e5010 = video_drvdata(file); + struct e5010_context *ctx = file->private_data; + + dprintk(e5010, 1, "Releasing instance: 0x%p, m2m_ctx: 0x%p\n", ctx, ctx->fh.m2m_ctx); + mutex_lock(&e5010->mutex); + v4l2_ctrl_handler_free(&ctx->ctrl_handler); + v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); + v4l2_fh_del(&ctx->fh); + v4l2_fh_exit(&ctx->fh); + kfree(ctx); + mutex_unlock(&e5010->mutex); + + return 0; +} + +static void header_write(struct e5010_context *ctx, u8 *addr, unsigned int *offset, + unsigned int no_bytes, unsigned long bits) +{ + u8 *w_addr = addr + *offset; + int i; + + if ((*offset + no_bytes) > HEADER_SIZE) { + v4l2_warn(&ctx->e5010->v4l2_dev, "%s: %s: %d: Problem writing header. %d > HEADER_SIZE %d\n", + __FILE__, __func__, __LINE__, *offset + no_bytes, HEADER_SIZE); + return; + } + + for (i = no_bytes - 1; i >= 0; i--) + *(w_addr++) = ((u8 *)&bits)[i]; + + *offset += no_bytes; +} + +static void encode_marker_segment(struct e5010_context *ctx, void *addr, unsigned int *offset) +{ + u8 *buffer = (u8 *)addr; + int i; + + header_write(ctx, buffer, offset, 2, START_OF_IMAGE); + header_write(ctx, buffer, offset, 2, DQT_MARKER); + header_write(ctx, buffer, offset, 3, LQPQ << 4); + for (i = 0; i < PELS_IN_BLOCK; i++) + header_write(ctx, buffer, offset, 1, ctx->luma_qp[zigzag[i]]); + + header_write(ctx, buffer, offset, 2, DQT_MARKER); + header_write(ctx, buffer, offset, 3, (LQPQ << 4) | 1); + for (i = 0; i < PELS_IN_BLOCK; i++) + header_write(ctx, buffer, offset, 1, ctx->chroma_qp[zigzag[i]]); + + /* Huffman tables */ + header_write(ctx, buffer, offset, 2, DHT_MARKER); + header_write(ctx, buffer, offset, 2, LH_DC); + header_write(ctx, buffer, offset, 1, JPEG_LUM_HT | JPEG_DC_HT); + for (i = 0 ; i < ARRAY_SIZE(luma_dc_table); i++) + header_write(ctx, buffer, offset, 1, luma_dc_table[i]); + + header_write(ctx, buffer, offset, 2, DHT_MARKER); + header_write(ctx, buffer, offset, 2, LH_AC); + header_write(ctx, buffer, offset, 1, JPEG_LUM_HT | JPEG_AC_HT); + for (i = 0 ; i < ARRAY_SIZE(luma_ac_table); i++) + header_write(ctx, buffer, offset, 1, luma_ac_table[i]); + + header_write(ctx, buffer, offset, 2, DHT_MARKER); + header_write(ctx, buffer, offset, 2, LH_DC); + header_write(ctx, buffer, offset, 1, JPEG_CHR_HT | JPEG_DC_HT); + for (i = 0 ; i < ARRAY_SIZE(chroma_dc_table); i++) + header_write(ctx, buffer, offset, 1, chroma_dc_table[i]); + + header_write(ctx, buffer, offset, 2, DHT_MARKER); + header_write(ctx, buffer, offset, 2, LH_AC); + header_write(ctx, buffer, offset, 1, JPEG_CHR_HT | JPEG_AC_HT); + for (i = 0 ; i < ARRAY_SIZE(chroma_ac_table); i++) + header_write(ctx, buffer, offset, 1, chroma_ac_table[i]); +} + +static void encode_frame_header(struct e5010_context *ctx, void *addr, unsigned int *offset) +{ + u8 *buffer = (u8 *)addr; + + header_write(ctx, buffer, offset, 2, SOF_BASELINE_DCT); + header_write(ctx, buffer, offset, 2, 8 + (3 * UC_NUM_COMP)); + header_write(ctx, buffer, offset, 1, PRECISION); + header_write(ctx, buffer, offset, 2, ctx->out_queue.crop.height); + header_write(ctx, buffer, offset, 2, ctx->out_queue.crop.width); + header_write(ctx, buffer, offset, 1, UC_NUM_COMP); + + /* Luma details */ + header_write(ctx, buffer, offset, 1, 1); + if (ctx->out_queue.fmt->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_422) + header_write(ctx, buffer, offset, 1, + HORZ_SAMPLING_FACTOR | (VERT_SAMPLING_FACTOR_422)); + else + header_write(ctx, buffer, offset, 1, + HORZ_SAMPLING_FACTOR | (VERT_SAMPLING_FACTOR_420)); + header_write(ctx, buffer, offset, 1, 0); + /* Chroma details */ + header_write(ctx, buffer, offset, 1, 2); + header_write(ctx, buffer, offset, 1, (HORZ_SAMPLING_FACTOR >> 1) | 1); + header_write(ctx, buffer, offset, 1, 1); + header_write(ctx, buffer, offset, 1, 3); + header_write(ctx, buffer, offset, 1, (HORZ_SAMPLING_FACTOR >> 1) | 1); + header_write(ctx, buffer, offset, 1, 1); +} + +static void jpg_encode_sos_header(struct e5010_context *ctx, void *addr, unsigned int *offset) +{ + u8 *buffer = (u8 *)addr; + int i; + + header_write(ctx, buffer, offset, 2, START_OF_SCAN); + header_write(ctx, buffer, offset, 2, 6 + (COMPONENTS_IN_SCAN << 1)); + header_write(ctx, buffer, offset, 1, COMPONENTS_IN_SCAN); + + for (i = 0; i < COMPONENTS_IN_SCAN; i++) { + header_write(ctx, buffer, offset, 1, i + 1); + if (i == 0) + header_write(ctx, buffer, offset, 1, 0); + else + header_write(ctx, buffer, offset, 1, 17); + } + + header_write(ctx, buffer, offset, 1, 0); + header_write(ctx, buffer, offset, 1, 63); + header_write(ctx, buffer, offset, 1, 0); +} + +static void write_header(struct e5010_context *ctx, void *addr) +{ + unsigned int offset = 0; + + encode_marker_segment(ctx, addr, &offset); + encode_frame_header(ctx, addr, &offset); + jpg_encode_sos_header(ctx, addr, &offset); +} + +static irqreturn_t e5010_irq(int irq, void *data) +{ + struct e5010_dev *e5010 = data; + struct e5010_context *ctx; + int output_size; + struct vb2_v4l2_buffer *src_buf, *dst_buf; + bool pic_done, out_addr_err; + + spin_lock(&e5010->hw_lock); + pic_done = e5010_hw_pic_done_irq(e5010->core_base); + out_addr_err = e5010_hw_output_address_irq(e5010->core_base); + + if (!pic_done && !out_addr_err) { + spin_unlock(&e5010->hw_lock); + return IRQ_NONE; + } + + ctx = v4l2_m2m_get_curr_priv(e5010->m2m_dev); + if (WARN_ON(!ctx)) + goto job_unlock; + + dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); + src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); + if (!dst_buf || !src_buf) { + v4l2_err(&e5010->v4l2_dev, "ctx: 0x%p No source or destination buffer\n", ctx); + goto job_unlock; + } + + if (out_addr_err) { + e5010_hw_clear_output_error(e5010->core_base, 1); + v4l2_warn(&e5010->v4l2_dev, + "ctx: 0x%p Output bitstream size exceeded max size\n", ctx); + v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR); + vb2_set_plane_payload(&dst_buf->vb2_buf, 0, dst_buf->planes[0].length); + v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR); + if (v4l2_m2m_is_last_draining_src_buf(ctx->fh.m2m_ctx, src_buf)) { + dst_buf->flags |= V4L2_BUF_FLAG_LAST; + v4l2_m2m_mark_stopped(ctx->fh.m2m_ctx); + v4l2_event_queue_fh(&ctx->fh, &e5010_eos_event); + dprintk(e5010, 2, "ctx: 0x%p Sending EOS\n", ctx); + } + } + + if (pic_done) { + e5010_hw_clear_picture_done(e5010->core_base, 1); + dprintk(e5010, 3, "ctx: 0x%p Got output bitstream of size %d bytes\n", + ctx, readl(e5010->core_base + JASPER_OUTPUT_SIZE_OFFSET)); + + if (v4l2_m2m_is_last_draining_src_buf(ctx->fh.m2m_ctx, src_buf)) { + dst_buf->flags |= V4L2_BUF_FLAG_LAST; + v4l2_m2m_mark_stopped(ctx->fh.m2m_ctx); + v4l2_event_queue_fh(&ctx->fh, &e5010_eos_event); + dprintk(e5010, 2, "ctx: 0x%p Sending EOS\n", ctx); + } + v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); + output_size = e5010_hw_get_output_size(e5010->core_base); + vb2_set_plane_payload(&dst_buf->vb2_buf, 0, output_size + HEADER_SIZE); + v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); + dprintk(e5010, 3, + "ctx: 0x%p frame done for dst_buf->sequence: %d src_buf->sequence: %d\n", + ctx, dst_buf->sequence, src_buf->sequence); + } + + v4l2_m2m_job_finish(e5010->m2m_dev, ctx->fh.m2m_ctx); + dprintk(e5010, 3, "ctx: 0x%p Finish job\n", ctx); + +job_unlock: + spin_unlock(&e5010->hw_lock); + return IRQ_HANDLED; +} + +static int e5010_init_device(struct e5010_dev *e5010) +{ + int ret = 0; + + /*TODO: Set MMU in bypass mode until support for the same is added in driver*/ + e5010_hw_bypass_mmu(e5010->mmu_base, 1); + + if (e5010_hw_enable_auto_clock_gating(e5010->core_base, 1)) + v4l2_warn(&e5010->v4l2_dev, "failed to enable auto clock gating\n"); + + if (e5010_hw_enable_manual_clock_gating(e5010->core_base, 0)) + v4l2_warn(&e5010->v4l2_dev, "failed to disable manual clock gating\n"); + + if (e5010_hw_enable_crc_check(e5010->core_base, 0)) + v4l2_warn(&e5010->v4l2_dev, "failed to disable CRC check\n"); + + if (e5010_hw_enable_output_address_error_irq(e5010->core_base, 1)) + v4l2_err(&e5010->v4l2_dev, "failed to enable Output Address Error interrupts\n"); + + ret = e5010_hw_set_input_source_to_memory(e5010->core_base, 1); + if (ret) { + v4l2_err(&e5010->v4l2_dev, "failed to set input source to memory\n"); + return ret; + } + + ret = e5010_hw_enable_picture_done_irq(e5010->core_base, 1); + if (ret) + v4l2_err(&e5010->v4l2_dev, "failed to enable Picture Done interrupts\n"); + + return ret; +} + +static int e5010_probe(struct platform_device *pdev) +{ + struct e5010_dev *e5010; + int irq, ret = 0; + struct device *dev = &pdev->dev; + + ret = dma_set_mask(dev, DMA_BIT_MASK(32)); + if (ret) + return dev_err_probe(dev, ret, "32-bit consistent DMA enable failed\n"); + + e5010 = devm_kzalloc(dev, sizeof(*e5010), GFP_KERNEL); + if (!e5010) + return -ENOMEM; + + platform_set_drvdata(pdev, e5010); + + e5010->dev = dev; + + mutex_init(&e5010->mutex); + spin_lock_init(&e5010->hw_lock); + + e5010->vdev = video_device_alloc(); + if (!e5010->vdev) { + dev_err(dev, "failed to allocate video device\n"); + return -ENOMEM; + } + + snprintf(e5010->vdev->name, sizeof(e5010->vdev->name), "%s", E5010_MODULE_NAME); + e5010->vdev->fops = &e5010_fops; + e5010->vdev->ioctl_ops = &e5010_ioctl_ops; + e5010->vdev->minor = -1; + e5010->vdev->release = video_device_release; + e5010->vdev->vfl_dir = VFL_DIR_M2M; + e5010->vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; + e5010->vdev->v4l2_dev = &e5010->v4l2_dev; + e5010->vdev->lock = &e5010->mutex; + + ret = v4l2_device_register(dev, &e5010->v4l2_dev); + if (ret) + return dev_err_probe(dev, ret, "failed to register v4l2 device\n"); + + e5010->m2m_dev = v4l2_m2m_init(&e5010_m2m_ops); + if (IS_ERR(e5010->m2m_dev)) { + ret = PTR_ERR(e5010->m2m_dev); + e5010->m2m_dev = NULL; + dev_err_probe(dev, ret, "failed to init mem2mem device\n"); + goto fail_after_v4l2_register; + } + + video_set_drvdata(e5010->vdev, e5010); + + e5010->core_base = devm_platform_ioremap_resource_byname(pdev, "core"); + if (IS_ERR(e5010->core_base)) { + ret = PTR_ERR(e5010->core_base); + dev_err_probe(dev, ret, "Missing 'core' resources area\n"); + goto fail_after_v4l2_register; + } + + e5010->mmu_base = devm_platform_ioremap_resource_byname(pdev, "mmu"); + if (IS_ERR(e5010->mmu_base)) { + ret = PTR_ERR(e5010->mmu_base); + dev_err_probe(dev, ret, "Missing 'mmu' resources area\n"); + goto fail_after_v4l2_register; + } + + e5010->last_context_run = NULL; + + irq = platform_get_irq(pdev, 0); + ret = devm_request_irq(dev, irq, e5010_irq, 0, + E5010_MODULE_NAME, e5010); + if (ret) { + dev_err_probe(dev, ret, "failed to register IRQ %d\n", irq); + goto fail_after_v4l2_register; + } + + e5010->clk = devm_clk_get(dev, NULL); + if (IS_ERR(e5010->clk)) { + ret = PTR_ERR(e5010->clk); + dev_err_probe(dev, ret, "failed to get clock\n"); + goto fail_after_v4l2_register; + } + + pm_runtime_enable(dev); + + ret = video_register_device(e5010->vdev, VFL_TYPE_VIDEO, 0); + if (ret) { + dev_err_probe(dev, ret, "failed to register video device\n"); + goto fail_after_video_register_device; + } + + v4l2_info(&e5010->v4l2_dev, "Device registered as /dev/video%d\n", + e5010->vdev->num); + + return 0; + +fail_after_video_register_device: + v4l2_m2m_release(e5010->m2m_dev); +fail_after_v4l2_register: + v4l2_device_unregister(&e5010->v4l2_dev); + return ret; +} + +static int e5010_remove(struct platform_device *pdev) +{ + struct e5010_dev *e5010 = platform_get_drvdata(pdev); + + pm_runtime_disable(e5010->dev); + video_unregister_device(e5010->vdev); + v4l2_m2m_release(e5010->m2m_dev); + v4l2_device_unregister(&e5010->v4l2_dev); + + return 0; +} + +static void e5010_vb2_buffers_return(struct vb2_queue *q, enum vb2_buffer_state state) +{ + struct vb2_v4l2_buffer *vbuf; + struct e5010_context *ctx = vb2_get_drv_priv(q); + + if (V4L2_TYPE_IS_OUTPUT(q->type)) { + while ((vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx))) { + dprintk(ctx->e5010, 2, "ctx: 0x%p, buf type %s | index %d\n", + ctx, type_name(vbuf->vb2_buf.type), vbuf->vb2_buf.index); + v4l2_m2m_buf_done(vbuf, state); + } + } else { + while ((vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx))) { + dprintk(ctx->e5010, 2, "ctx: 0x%p, buf type %s | index %d\n", + ctx, type_name(vbuf->vb2_buf.type), vbuf->vb2_buf.index); + vb2_set_plane_payload(&vbuf->vb2_buf, 0, 0); + v4l2_m2m_buf_done(vbuf, state); + } + } +} + +static int e5010_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, + unsigned int sizes[], struct device *alloc_devs[]) +{ + struct e5010_context *ctx = vb2_get_drv_priv(vq); + struct e5010_q_data *queue; + int i; + + queue = get_queue(ctx, vq->type); + + if (*nplanes) { + if (*nplanes != queue->fmt->num_planes) + return -EINVAL; + for (i = 0; i < *nplanes; i++) { + if (sizes[i] < queue->sizeimage[i]) + return -EINVAL; + } + return 0; + } + + *nplanes = queue->fmt->num_planes; + for (i = 0; i < *nplanes; i++) + sizes[i] = queue->sizeimage[i]; + + dprintk(ctx->e5010, 2, + "ctx: 0x%p, type %s, buffer(s): %d, planes %d, plane1: bytes %d plane2: %d bytes\n", + ctx, type_name(vq->type), *nbuffers, *nplanes, sizes[0], sizes[1]); + + return 0; +} + +static void e5010_buf_finish(struct vb2_buffer *vb) +{ + struct e5010_context *ctx = vb2_get_drv_priv(vb->vb2_queue); + void *d_addr; + + if (vb->state != VB2_BUF_STATE_DONE || V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) + return; + + d_addr = vb2_plane_vaddr(vb, 0); + write_header(ctx, d_addr); +} + +static int e5010_buf_out_validate(struct vb2_buffer *vb) +{ + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct e5010_context *ctx = vb2_get_drv_priv(vb->vb2_queue); + + if (vbuf->field != V4L2_FIELD_NONE) + dprintk(ctx->e5010, 1, "ctx: 0x%p, field isn't supported\n", ctx); + + vbuf->field = V4L2_FIELD_NONE; + + return 0; +} + +static int e5010_buf_prepare(struct vb2_buffer *vb) +{ + struct e5010_context *ctx = vb2_get_drv_priv(vb->vb2_queue); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct e5010_q_data *queue; + int i; + + vbuf->field = V4L2_FIELD_NONE; + + queue = get_queue(ctx, vb->vb2_queue->type); + + for (i = 0; i < queue->fmt->num_planes; i++) { + if (vb2_plane_size(vb, i) < (unsigned long)queue->sizeimage[i]) { + v4l2_err(&ctx->e5010->v4l2_dev, "plane %d too small (%lu < %lu)", i, + vb2_plane_size(vb, i), (unsigned long)queue->sizeimage[i]); + + return -EINVAL; + } + } + + if (V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type)) { + vb2_set_plane_payload(vb, 0, 0); + vb2_set_plane_payload(vb, 1, 0); + } + + return 0; +} + +static void e5010_buf_queue(struct vb2_buffer *vb) +{ + struct e5010_context *ctx = vb2_get_drv_priv(vb->vb2_queue); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + + if (V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type) && + vb2_is_streaming(vb->vb2_queue) && + v4l2_m2m_dst_buf_is_last(ctx->fh.m2m_ctx)) { + struct e5010_q_data *queue = get_queue(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + + vbuf->sequence = queue->sequence++; + v4l2_m2m_last_buffer_done(ctx->fh.m2m_ctx, vbuf); + v4l2_event_queue_fh(&ctx->fh, &e5010_eos_event); + return; + } + + v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); +} + +static int e5010_encoder_cmd(struct file *file, void *priv, + struct v4l2_encoder_cmd *cmd) +{ + struct e5010_context *ctx = file->private_data; + int ret; + struct vb2_queue *cap_vq; + + cap_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + + ret = v4l2_m2m_ioctl_try_encoder_cmd(file, &ctx->fh, cmd); + if (ret < 0) + return ret; + + if (!vb2_is_streaming(v4l2_m2m_get_src_vq(ctx->fh.m2m_ctx)) || + !vb2_is_streaming(v4l2_m2m_get_dst_vq(ctx->fh.m2m_ctx))) + return 0; + + ret = v4l2_m2m_ioctl_encoder_cmd(file, &ctx->fh, cmd); + if (ret < 0) + return ret; + + if (cmd->cmd == V4L2_ENC_CMD_STOP && + v4l2_m2m_has_stopped(ctx->fh.m2m_ctx)) + v4l2_event_queue_fh(&ctx->fh, &e5010_eos_event); + + if (cmd->cmd == V4L2_ENC_CMD_START && + v4l2_m2m_has_stopped(ctx->fh.m2m_ctx)) + vb2_clear_last_buffer_dequeued(cap_vq); + + return 0; +} + +static int e5010_start_streaming(struct vb2_queue *q, unsigned int count) +{ + struct e5010_context *ctx = vb2_get_drv_priv(q); + int ret; + + struct e5010_q_data *queue = get_queue(ctx, q->type); + + v4l2_m2m_update_start_streaming_state(ctx->fh.m2m_ctx, q); + queue->sequence = 0; + + ret = pm_runtime_resume_and_get(ctx->e5010->dev); + if (ret < 0) { + v4l2_err(&ctx->e5010->v4l2_dev, "failed to power up jpeg\n"); + goto fail; + } + + ret = e5010_init_device(ctx->e5010); + if (ret) { + v4l2_err(&ctx->e5010->v4l2_dev, "failed to Enable e5010 device\n"); + goto fail; + } + + return 0; + +fail: + e5010_vb2_buffers_return(q, VB2_BUF_STATE_QUEUED); + + return ret; +} + +static void e5010_stop_streaming(struct vb2_queue *q) +{ + struct e5010_context *ctx = vb2_get_drv_priv(q); + + e5010_vb2_buffers_return(q, VB2_BUF_STATE_ERROR); + + if (V4L2_TYPE_IS_OUTPUT(q->type)) + v4l2_m2m_update_stop_streaming_state(ctx->fh.m2m_ctx, q); + + if (V4L2_TYPE_IS_OUTPUT(q->type) && + v4l2_m2m_has_stopped(ctx->fh.m2m_ctx)) { + v4l2_event_queue_fh(&ctx->fh, &e5010_eos_event); + } + + pm_runtime_put_sync(ctx->e5010->dev); +} + +static void e5010_device_run(void *priv) +{ + struct e5010_context *ctx = priv; + struct e5010_dev *e5010 = ctx->e5010; + struct vb2_v4l2_buffer *s_vb, *d_vb; + u32 reg = 0; + int ret = 0, luma_crop_offset = 0, chroma_crop_offset = 0; + unsigned long flags; + int num_planes = ctx->out_queue.fmt->num_planes; + + spin_lock_irqsave(&e5010->hw_lock, flags); + s_vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); + WARN_ON(!s_vb); + d_vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); + WARN_ON(!d_vb); + if (!s_vb || !d_vb) + goto no_ready_buf_err; + + s_vb->sequence = ctx->out_queue.sequence++; + d_vb->sequence = ctx->cap_queue.sequence++; + + v4l2_m2m_buf_copy_metadata(s_vb, d_vb, false); + + if (ctx != e5010->last_context_run || ctx->update_qp) { + dprintk(e5010, 1, "ctx updated: 0x%p -> 0x%p, updating qp tables\n", + e5010->last_context_run, ctx); + ret = update_qp_tables(ctx); + } + + if (ret) { + ctx->update_qp = true; + v4l2_err(&e5010->v4l2_dev, "failed to update QP tables\n"); + goto device_busy_err; + } else { + e5010->last_context_run = ctx; + ctx->update_qp = false; + } + + /* Set I/O Buffer addresses */ + reg = (u32)vb2_dma_contig_plane_dma_addr(&s_vb->vb2_buf, 0); + + if (ctx->out_queue.crop_set) { + luma_crop_offset = ctx->out_queue.bytesperline[0] * ctx->out_queue.crop.top + + ctx->out_queue.crop.left; + + if (ctx->out_queue.fmt->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_422) { + chroma_crop_offset = + ctx->out_queue.bytesperline[0] * ctx->out_queue.crop.top + + ctx->out_queue.crop.left; + } else { + chroma_crop_offset = + ctx->out_queue.bytesperline[0] * ctx->out_queue.crop.top / 2 + + ctx->out_queue.crop.left; + } + + dprintk(e5010, 1, "Luma crop offset : %x, chroma crop offset : %x\n", + luma_crop_offset, chroma_crop_offset); + } + + ret = e5010_hw_set_input_luma_addr(e5010->core_base, reg + luma_crop_offset); + if (ret || !reg) { + v4l2_err(&e5010->v4l2_dev, "failed to set input luma address\n"); + goto device_busy_err; + } + + if (num_planes == 1) + reg += (ctx->out_queue.bytesperline[0]) * (ctx->out_queue.height); + else + reg = (u32)vb2_dma_contig_plane_dma_addr(&s_vb->vb2_buf, 1); + + dprintk(e5010, 3, + "ctx: 0x%p, luma_addr: 0x%x, chroma_addr: 0x%x, out_addr: 0x%x\n", + ctx, (u32)vb2_dma_contig_plane_dma_addr(&s_vb->vb2_buf, 0) + luma_crop_offset, + reg + chroma_crop_offset, (u32)vb2_dma_contig_plane_dma_addr(&d_vb->vb2_buf, 0)); + + dprintk(e5010, 3, + "ctx: 0x%p, buf indices: src_index: %d, dst_index: %d\n", + ctx, s_vb->vb2_buf.index, d_vb->vb2_buf.index); + + ret = e5010_hw_set_input_chroma_addr(e5010->core_base, reg + chroma_crop_offset); + if (ret || !reg) { + v4l2_err(&e5010->v4l2_dev, "failed to set input chroma address\n"); + goto device_busy_err; + } + + reg = (u32)vb2_dma_contig_plane_dma_addr(&d_vb->vb2_buf, 0); + reg += HEADER_SIZE; + ret = e5010_hw_set_output_base_addr(e5010->core_base, reg); + if (ret || !reg) { + v4l2_err(&e5010->v4l2_dev, "failed to set output base address\n"); + goto device_busy_err; + } + + /* Set input settings */ + ret = e5010_hw_set_horizontal_size(e5010->core_base, ctx->out_queue.crop.width - 1); + if (ret) { + v4l2_err(&e5010->v4l2_dev, "failed to set input width\n"); + goto device_busy_err; + } + + ret = e5010_hw_set_vertical_size(e5010->core_base, ctx->out_queue.crop.height - 1); + if (ret) { + v4l2_err(&e5010->v4l2_dev, "failed to set input width\n"); + goto device_busy_err; + } + + ret = e5010_hw_set_luma_stride(e5010->core_base, ctx->out_queue.bytesperline[0]); + if (ret) { + v4l2_err(&e5010->v4l2_dev, "failed to set luma stride\n"); + goto device_busy_err; + } + + ret = e5010_hw_set_chroma_stride(e5010->core_base, ctx->out_queue.bytesperline[0]); + if (ret) { + v4l2_err(&e5010->v4l2_dev, "failed to set chroma stride\n"); + goto device_busy_err; + } + + ret = e5010_set_input_subsampling(e5010->core_base, ctx->out_queue.fmt->subsampling); + if (ret) { + v4l2_err(&e5010->v4l2_dev, "failed to set input subsampling\n"); + goto device_busy_err; + } + + ret = e5010_hw_set_chroma_order(e5010->core_base, ctx->out_queue.fmt->chroma_order); + if (ret) { + v4l2_err(&e5010->v4l2_dev, "failed to set chroma order\n"); + goto device_busy_err; + } + + e5010_hw_set_output_max_size(e5010->core_base, d_vb->planes[0].length); + e5010_hw_encode_start(e5010->core_base, 1); + + spin_unlock_irqrestore(&e5010->hw_lock, flags); + + return; + +device_busy_err: + e5010_reset(e5010->dev, e5010->core_base, e5010->mmu_base); + +no_ready_buf_err: + if (s_vb) { + v4l2_m2m_src_buf_remove_by_buf(ctx->fh.m2m_ctx, s_vb); + v4l2_m2m_buf_done(s_vb, VB2_BUF_STATE_ERROR); + } + + if (d_vb) { + v4l2_m2m_dst_buf_remove_by_buf(ctx->fh.m2m_ctx, d_vb); + /* Payload set to 1 since 0 payload can trigger EOS */ + vb2_set_plane_payload(&d_vb->vb2_buf, 0, 1); + v4l2_m2m_buf_done(d_vb, VB2_BUF_STATE_ERROR); + } + v4l2_m2m_job_finish(e5010->m2m_dev, ctx->fh.m2m_ctx); + spin_unlock_irqrestore(&e5010->hw_lock, flags); +} + +#ifdef CONFIG_PM +static int e5010_runtime_resume(struct device *dev) +{ + struct e5010_dev *e5010 = dev_get_drvdata(dev); + int ret; + + ret = clk_prepare_enable(e5010->clk); + if (ret < 0) { + v4l2_err(&e5010->v4l2_dev, "failed to enable clock\n"); + return ret; + } + + return 0; +} + +static int e5010_runtime_suspend(struct device *dev) +{ + struct e5010_dev *e5010 = dev_get_drvdata(dev); + + clk_disable_unprepare(e5010->clk); + + return 0; +} +#endif + +#ifdef CONFIG_PM_SLEEP +static int e5010_suspend(struct device *dev) +{ + struct e5010_dev *e5010 = dev_get_drvdata(dev); + + v4l2_m2m_suspend(e5010->m2m_dev); + + return pm_runtime_force_suspend(dev); +} + +static int e5010_resume(struct device *dev) +{ + struct e5010_dev *e5010 = dev_get_drvdata(dev); + int ret; + + ret = pm_runtime_force_resume(dev); + if (ret < 0) + return ret; + + ret = e5010_init_device(e5010); + if (ret) { + dev_err(dev, "Failed to re-enable e5010 device\n"); + return ret; + } + + v4l2_m2m_resume(e5010->m2m_dev); + + return ret; +} +#endif + +static const struct dev_pm_ops e5010_pm_ops = { + SET_RUNTIME_PM_OPS(e5010_runtime_suspend, + e5010_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(e5010_suspend, e5010_resume) +}; + +static const struct v4l2_ioctl_ops e5010_ioctl_ops = { + .vidioc_querycap = e5010_querycap, + + .vidioc_enum_fmt_vid_cap = e5010_enum_fmt, + .vidioc_g_fmt_vid_cap_mplane = e5010_g_fmt, + .vidioc_try_fmt_vid_cap_mplane = e5010_try_fmt, + .vidioc_s_fmt_vid_cap_mplane = e5010_s_fmt, + + .vidioc_enum_fmt_vid_out = e5010_enum_fmt, + .vidioc_g_fmt_vid_out_mplane = e5010_g_fmt, + .vidioc_try_fmt_vid_out_mplane = e5010_try_fmt, + .vidioc_s_fmt_vid_out_mplane = e5010_s_fmt, + + .vidioc_g_selection = e5010_g_selection, + .vidioc_s_selection = e5010_s_selection, + + .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, + .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, + .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, + .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, + .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, + .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, + .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, + + .vidioc_streamon = v4l2_m2m_ioctl_streamon, + .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, + .vidioc_log_status = v4l2_ctrl_log_status, + + .vidioc_subscribe_event = e5010_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, + .vidioc_try_encoder_cmd = v4l2_m2m_ioctl_try_encoder_cmd, + .vidioc_encoder_cmd = e5010_encoder_cmd, + + .vidioc_enum_framesizes = e5010_enum_framesizes, +}; + +static const struct vb2_ops e5010_video_ops = { + .queue_setup = e5010_queue_setup, + .buf_queue = e5010_buf_queue, + .buf_finish = e5010_buf_finish, + .buf_prepare = e5010_buf_prepare, + .buf_out_validate = e5010_buf_out_validate, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, + .start_streaming = e5010_start_streaming, + .stop_streaming = e5010_stop_streaming, +}; + +static const struct v4l2_file_operations e5010_fops = { + .owner = THIS_MODULE, + .open = e5010_open, + .release = e5010_release, + .poll = v4l2_m2m_fop_poll, + .unlocked_ioctl = video_ioctl2, + .mmap = v4l2_m2m_fop_mmap, +}; + +static const struct v4l2_m2m_ops e5010_m2m_ops = { + .device_run = e5010_device_run, +}; + +static const struct of_device_id e5010_of_match[] = { + {.compatible = "img,e5010-jpeg-enc"}, { /* end */}, +}; +MODULE_DEVICE_TABLE(of, e5010_of_match); + +static struct platform_driver e5010_driver = { + .probe = e5010_probe, + .remove = e5010_remove, + .driver = { + .name = E5010_MODULE_NAME, + .of_match_table = e5010_of_match, + .pm = &e5010_pm_ops, + }, +}; +module_platform_driver(e5010_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Imagination E5010 JPEG encoder driver"); diff --git a/drivers/media/platform/imagination/e5010-jpeg-enc.h b/drivers/media/platform/imagination/e5010-jpeg-enc.h new file mode 100644 index 000000000000..71f49ead6898 --- /dev/null +++ b/drivers/media/platform/imagination/e5010-jpeg-enc.h @@ -0,0 +1,168 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Imagination E5010 JPEG Encoder driver. + * + * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/ + * + * Author: David Huang + * Author: Devarsh Thakkar + */ + +#include +#include +#include + +#ifndef _E5010_JPEG_ENC_H +#define _E5010_JPEG_ENC_H + +#define MAX_PLANES 2 +#define HEADER_SIZE 0x025D +#define MIN_DIMENSION 64 +#define MAX_DIMENSION 8192 +#define DEFAULT_WIDTH 640 +#define DEFAULT_HEIGHT 480 +#define E5010_MODULE_NAME "e5010" +#define JPEG_MAX_BYTES_PER_PIXEL 2 + +/* JPEG marker definitions */ +#define START_OF_IMAGE 0xFFD8 +#define SOF_BASELINE_DCT 0xFFC0 +#define END_OF_IMAGE 0xFFD9 +#define START_OF_SCAN 0xFFDA + +/* Definitions for the huffman table specification in the Marker segment */ +#define DHT_MARKER 0xFFC4 +#define LH_DC 0x001F +#define LH_AC 0x00B5 + +/* Definitions for the quantization table specification in the Marker segment */ +#define DQT_MARKER 0xFFDB +#define ACMAX 0x03FF +#define DCMAX 0x07FF + +/* Length and precision of the quantization table parameters */ +#define LQPQ 0x00430 +#define QMAX 255 + +/* Misc JPEG header definitions */ +#define UC_NUM_COMP 3 +#define PRECISION 8 +#define HORZ_SAMPLING_FACTOR (2 << 4) +#define VERT_SAMPLING_FACTOR_422 1 +#define VERT_SAMPLING_FACTOR_420 2 +#define COMPONENTS_IN_SCAN 3 +#define PELS_IN_BLOCK 64 + +/* Used for Qp table generation */ +#define LUMINOSITY 10 +#define CONTRAST 1 +#define INCREASE 2 +#define QP_TABLE_SIZE (8 * 8) +#define QP_TABLE_FIELD_OFFSET 0x04 + +/* + * vb2 queue structure + * contains queue data information + * + * @fmt: format info + * @width: frame width + * @height: frame height + * @bytesperline: bytes per line in memory + * @size_image: image size in memory + */ +struct e5010_q_data { + struct e5010_fmt *fmt; + u32 width; + u32 height; + u32 width_adjusted; + u32 height_adjusted; + u32 sizeimage[MAX_PLANES]; + u32 bytesperline[MAX_PLANES]; + u32 sequence; + struct v4l2_rect crop; + bool crop_set; +}; + +/* + * Driver device structure + * Holds all memory handles and global parameters + * Shared by all instances + */ +struct e5010_dev { + struct device *dev; + struct v4l2_device v4l2_dev; + struct v4l2_m2m_dev *m2m_dev; + struct video_device *vdev; + void __iomem *core_base; + void __iomem *mmu_base; + struct clk *clk; + struct e5010_context *last_context_run; + /* Protect access to device data */ + struct mutex mutex; + /* Protect access to hardware*/ + spinlock_t hw_lock; +}; + +/* + * Driver context structure + * One of these exists for every m2m context + * Holds context specific data + */ +struct e5010_context { + struct v4l2_fh fh; + struct e5010_dev *e5010; + struct e5010_q_data out_queue; + struct e5010_q_data cap_queue; + int quality; + bool update_qp; + struct v4l2_ctrl_handler ctrl_handler; + u8 luma_qp[QP_TABLE_SIZE]; + u8 chroma_qp[QP_TABLE_SIZE]; +}; + +/* + * Buffer structure + * Contains info for all buffers + */ +struct e5010_buffer { + struct v4l2_m2m_buffer buffer; +}; + +enum { + CHROMA_ORDER_CB_CR = 0, //UV ordering + CHROMA_ORDER_CR_CB = 1, //VU ordering +}; + +enum { + SUBSAMPLING_420 = 1, + SUBSAMPLING_422 = 2, +}; + +/* + * e5010 format structure + * contains format information + */ +struct e5010_fmt { + u32 fourcc; + unsigned int num_planes; + unsigned int type; + u32 subsampling; + u32 chroma_order; + const struct v4l2_frmsize_stepwise frmsize; +}; + +/* + * struct e5010_ctrl - contains info for each supported v4l2 control + */ +struct e5010_ctrl { + unsigned int cid; + enum v4l2_ctrl_type type; + unsigned char name[32]; + int minimum; + int maximum; + int step; + int default_value; + unsigned char compound; +}; + +#endif diff --git a/drivers/media/platform/imagination/e5010-mmu-regs.h b/drivers/media/platform/imagination/e5010-mmu-regs.h new file mode 100644 index 000000000000..bfba06956cf2 --- /dev/null +++ b/drivers/media/platform/imagination/e5010-mmu-regs.h @@ -0,0 +1,311 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Imagination E5010 JPEG Encoder driver. + * + * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/ + * + * Author: David Huang + * Author: Devarsh Thakkar + */ + +#ifndef _E5010_MMU_REGS_H +#define _E5010_MMU_REGS_H + +#define MMU_MMU_DIR_BASE_ADDR_OFFSET (0x0020) +#define MMU_MMU_DIR_BASE_ADDR_STRIDE (4) +#define MMU_MMU_DIR_BASE_ADDR_NO_ENTRIES (4) + +#define MMU_MMU_DIR_BASE_ADDR_MMU_DIR_BASE_ADDR_MASK (0xFFFFFFFF) +#define MMU_MMU_DIR_BASE_ADDR_MMU_DIR_BASE_ADDR_SHIFT (0) + +#define MMU_MMU_TILE_CFG_OFFSET (0x0040) +#define MMU_MMU_TILE_CFG_STRIDE (4) +#define MMU_MMU_TILE_CFG_NO_ENTRIES (4) + +#define MMU_MMU_TILE_CFG_TILE_128INTERLEAVE_MASK (0x00000010) +#define MMU_MMU_TILE_CFG_TILE_128INTERLEAVE_SHIFT (4) + +#define MMU_MMU_TILE_CFG_TILE_ENABLE_MASK (0x00000008) +#define MMU_MMU_TILE_CFG_TILE_ENABLE_SHIFT (3) + +#define MMU_MMU_TILE_CFG_TILE_STRIDE_MASK (0x00000007) +#define MMU_MMU_TILE_CFG_TILE_STRIDE_SHIFT (0) + +#define MMU_MMU_TILE_MIN_ADDR_OFFSET (0x0050) +#define MMU_MMU_TILE_MIN_ADDR_STRIDE (4) +#define MMU_MMU_TILE_MIN_ADDR_NO_ENTRIES (4) + +#define MMU_MMU_TILE_MIN_ADDR_TILE_MIN_ADDR_MASK (0xFFFFFFFF) +#define MMU_MMU_TILE_MIN_ADDR_TILE_MIN_ADDR_SHIFT (0) + +#define MMU_MMU_TILE_MAX_ADDR_OFFSET (0x0060) +#define MMU_MMU_TILE_MAX_ADDR_STRIDE (4) +#define MMU_MMU_TILE_MAX_ADDR_NO_ENTRIES (4) + +#define MMU_MMU_TILE_MAX_ADDR_TILE_MAX_ADDR_MASK (0xFFFFFFFF) +#define MMU_MMU_TILE_MAX_ADDR_TILE_MAX_ADDR_SHIFT (0) + +#define MMU_MMU_CONTROL0_OFFSET (0x0000) + +#define MMU_MMU_CONTROL0_MMU_TILING_SCHEME_MASK (0x00000001) +#define MMU_MMU_CONTROL0_MMU_TILING_SCHEME_SHIFT (0) + +#define MMU_MMU_CONTROL0_MMU_CACHE_POLICY_MASK (0x00000100) +#define MMU_MMU_CONTROL0_MMU_CACHE_POLICY_SHIFT (8) + +#define MMU_MMU_CONTROL0_FORCE_CACHE_POLICY_BYPASS_MASK (0x00000200) +#define MMU_MMU_CONTROL0_FORCE_CACHE_POLICY_BYPASS_SHIFT (9) + +#define MMU_MMU_CONTROL0_STALL_ON_PROTOCOL_FAULT_MASK (0x00001000) +#define MMU_MMU_CONTROL0_STALL_ON_PROTOCOL_FAULT_SHIFT (12) + +#define MMU_MMU_CONTROL1_OFFSET (0x0008) + +#define MMU_MMU_CONTROL1_MMU_FLUSH_MASK (0x00000008) +#define MMU_MMU_CONTROL1_MMU_FLUSH_SHIFT (3) +#define MMU_MMU_CONTROL1_MMU_FLUSH_NO_REPS (4) +#define MMU_MMU_CONTROL1_MMU_FLUSH_SIZE (1) + +#define MMU_MMU_CONTROL1_MMU_INVALDC_MASK (0x00000800) +#define MMU_MMU_CONTROL1_MMU_INVALDC_SHIFT (11) +#define MMU_MMU_CONTROL1_MMU_INVALDC_NO_REPS (4) +#define MMU_MMU_CONTROL1_MMU_INVALDC_SIZE (1) + +#define MMU_MMU_CONTROL1_MMU_FAULT_CLEAR_MASK (0x00010000) +#define MMU_MMU_CONTROL1_MMU_FAULT_CLEAR_SHIFT (16) + +#define MMU_MMU_CONTROL1_PROTOCOL_FAULT_CLEAR_MASK (0x00100000) +#define MMU_MMU_CONTROL1_PROTOCOL_FAULT_CLEAR_SHIFT (20) + +#define MMU_MMU_CONTROL1_MMU_PAUSE_SET_MASK (0x01000000) +#define MMU_MMU_CONTROL1_MMU_PAUSE_SET_SHIFT (24) + +#define MMU_MMU_CONTROL1_MMU_PAUSE_CLEAR_MASK (0x02000000) +#define MMU_MMU_CONTROL1_MMU_PAUSE_CLEAR_SHIFT (25) + +#define MMU_MMU_CONTROL1_MMU_SOFT_RESET_MASK (0x10000000) +#define MMU_MMU_CONTROL1_MMU_SOFT_RESET_SHIFT (28) + +#define MMU_MMU_BANK_INDEX_OFFSET (0x0010) + +#define MMU_MMU_BANK_INDEX_MMU_BANK_INDEX_MASK (0xC0000000) +#define MMU_MMU_BANK_INDEX_MMU_BANK_INDEX_SHIFT (30) +#define MMU_MMU_BANK_INDEX_MMU_BANK_INDEX_NO_REPS (16) +#define MMU_MMU_BANK_INDEX_MMU_BANK_INDEX_SIZE (2) + +#define MMU_REQUEST_PRIORITY_ENABLE_OFFSET (0x0018) + +#define MMU_REQUEST_PRIORITY_ENABLE_CMD_PRIORITY_ENABLE_MASK (0x00008000) +#define MMU_REQUEST_PRIORITY_ENABLE_CMD_PRIORITY_ENABLE_SHIFT (15) +#define MMU_REQUEST_PRIORITY_ENABLE_CMD_PRIORITY_ENABLE_NO_REPS (16) +#define MMU_REQUEST_PRIORITY_ENABLE_CMD_PRIORITY_ENABLE_SIZE (1) + +#define MMU_REQUEST_PRIORITY_ENABLE_CMD_MMU_PRIORITY_ENABLE_MASK (0x00010000) +#define MMU_REQUEST_PRIORITY_ENABLE_CMD_MMU_PRIORITY_ENABLE_SHIFT (16) + +#define MMU_REQUEST_LIMITED_THROUGHPUT_OFFSET (0x001C) + +#define MMU_REQUEST_LIMITED_THROUGHPUT_LIMITED_WORDS_MASK (0x000003FF) +#define MMU_REQUEST_LIMITED_THROUGHPUT_LIMITED_WORDS_SHIFT (0) + +#define MMU_REQUEST_LIMITED_THROUGHPUT_REQUEST_GAP_MASK (0x0FFF0000) +#define MMU_REQUEST_LIMITED_THROUGHPUT_REQUEST_GAP_SHIFT (16) + +#define MMU_MMU_ADDRESS_CONTROL_OFFSET (0x0070) +#define MMU_MMU_ADDRESS_CONTROL_TRUSTED (IMG_TRUE) + +#define MMU_MMU_ADDRESS_CONTROL_MMU_BYPASS_MASK (0x00000001) +#define MMU_MMU_ADDRESS_CONTROL_MMU_BYPASS_SHIFT (0) + +#define MMU_MMU_ADDRESS_CONTROL_MMU_ENABLE_EXT_ADDRESSING_MASK (0x00000010) +#define MMU_MMU_ADDRESS_CONTROL_MMU_ENABLE_EXT_ADDRESSING_SHIFT (4) + +#define MMU_MMU_ADDRESS_CONTROL_UPPER_ADDRESS_FIXED_MASK (0x00FF0000) +#define MMU_MMU_ADDRESS_CONTROL_UPPER_ADDRESS_FIXED_SHIFT (16) + +#define MMU_MMU_CONFIG0_OFFSET (0x0080) + +#define MMU_MMU_CONFIG0_NUM_REQUESTORS_MASK (0x0000000F) +#define MMU_MMU_CONFIG0_NUM_REQUESTORS_SHIFT (0) + +#define MMU_MMU_CONFIG0_EXTENDED_ADDR_RANGE_MASK (0x000000F0) +#define MMU_MMU_CONFIG0_EXTENDED_ADDR_RANGE_SHIFT (4) + +#define MMU_MMU_CONFIG0_GROUP_OVERRIDE_SIZE_MASK (0x00000700) +#define MMU_MMU_CONFIG0_GROUP_OVERRIDE_SIZE_SHIFT (8) + +#define MMU_MMU_CONFIG0_ADDR_COHERENCY_SUPPORTED_MASK (0x00001000) +#define MMU_MMU_CONFIG0_ADDR_COHERENCY_SUPPORTED_SHIFT (12) + +#define MMU_MMU_CONFIG0_MMU_SUPPORTED_MASK (0x00002000) +#define MMU_MMU_CONFIG0_MMU_SUPPORTED_SHIFT (13) + +#define MMU_MMU_CONFIG0_TILE_ADDR_GRANULARITY_MASK (0x001F0000) +#define MMU_MMU_CONFIG0_TILE_ADDR_GRANULARITY_SHIFT (16) + +#define MMU_MMU_CONFIG0_NO_READ_REORDER_MASK (0x00200000) +#define MMU_MMU_CONFIG0_NO_READ_REORDER_SHIFT (21) + +#define MMU_MMU_CONFIG0_TAGS_SUPPORTED_MASK (0xFFC00000) +#define MMU_MMU_CONFIG0_TAGS_SUPPORTED_SHIFT (22) + +#define MMU_MMU_CONFIG1_OFFSET (0x0084) + +#define MMU_MMU_CONFIG1_PAGE_SIZE_MASK (0x0000000F) +#define MMU_MMU_CONFIG1_PAGE_SIZE_SHIFT (0) + +#define MMU_MMU_CONFIG1_PAGE_CACHE_ENTRIES_MASK (0x0000FF00) +#define MMU_MMU_CONFIG1_PAGE_CACHE_ENTRIES_SHIFT (8) + +#define MMU_MMU_CONFIG1_DIR_CACHE_ENTRIES_MASK (0x001F0000) +#define MMU_MMU_CONFIG1_DIR_CACHE_ENTRIES_SHIFT (16) + +#define MMU_MMU_CONFIG1_BANDWIDTH_COUNT_SUPPORTED_MASK (0x01000000) +#define MMU_MMU_CONFIG1_BANDWIDTH_COUNT_SUPPORTED_SHIFT (24) + +#define MMU_MMU_CONFIG1_STALL_COUNT_SUPPORTED_MASK (0x02000000) +#define MMU_MMU_CONFIG1_STALL_COUNT_SUPPORTED_SHIFT (25) + +#define MMU_MMU_CONFIG1_LATENCY_COUNT_SUPPORTED_MASK (0x04000000) +#define MMU_MMU_CONFIG1_LATENCY_COUNT_SUPPORTED_SHIFT (26) + +#define MMU_MMU_STATUS0_OFFSET (0x0088) + +#define MMU_MMU_STATUS0_MMU_PF_N_RW_MASK (0x00000001) +#define MMU_MMU_STATUS0_MMU_PF_N_RW_SHIFT (0) + +#define MMU_MMU_STATUS0_MMU_FAULT_ADDR_MASK (0xFFFFF000) +#define MMU_MMU_STATUS0_MMU_FAULT_ADDR_SHIFT (12) + +#define MMU_MMU_STATUS1_OFFSET (0x008C) + +#define MMU_MMU_STATUS1_MMU_FAULT_REQ_STAT_MASK (0x0000FFFF) +#define MMU_MMU_STATUS1_MMU_FAULT_REQ_STAT_SHIFT (0) + +#define MMU_MMU_STATUS1_MMU_FAULT_REQ_ID_MASK (0x000F0000) +#define MMU_MMU_STATUS1_MMU_FAULT_REQ_ID_SHIFT (16) + +#define MMU_MMU_STATUS1_MMU_FAULT_INDEX_MASK (0x03000000) +#define MMU_MMU_STATUS1_MMU_FAULT_INDEX_SHIFT (24) + +#define MMU_MMU_STATUS1_MMU_FAULT_RNW_MASK (0x10000000) +#define MMU_MMU_STATUS1_MMU_FAULT_RNW_SHIFT (28) + +#define MMU_MMU_MEM_REQ_OFFSET (0x0090) + +#define MMU_MMU_MEM_REQ_TAG_OUTSTANDING_MASK (0x000003FF) +#define MMU_MMU_MEM_REQ_TAG_OUTSTANDING_SHIFT (0) + +#define MMU_MMU_MEM_REQ_EXT_WRRESP_FAULT_MASK (0x00001000) +#define MMU_MMU_MEM_REQ_EXT_WRRESP_FAULT_SHIFT (12) + +#define MMU_MMU_MEM_REQ_EXT_RDRESP_FAULT_MASK (0x00002000) +#define MMU_MMU_MEM_REQ_EXT_RDRESP_FAULT_SHIFT (13) + +#define MMU_MMU_MEM_REQ_EXT_READ_BURST_FAULT_MASK (0x00004000) +#define MMU_MMU_MEM_REQ_EXT_READ_BURST_FAULT_SHIFT (14) + +#define MMU_MMU_MEM_REQ_INT_PROTOCOL_FAULT_MASK (0x80000000) +#define MMU_MMU_MEM_REQ_INT_PROTOCOL_FAULT_SHIFT (31) +#define MMU_MMU_MEM_REQ_INT_PROTOCOL_FAULT_NO_REPS (16) +#define MMU_MMU_MEM_REQ_INT_PROTOCOL_FAULT_SIZE (1) + +#define MMU_MMU_FAULT_SELECT_OFFSET (0x00A0) + +#define MMU_MMU_FAULT_SELECT_MMU_FAULT_SELECT_MASK (0x0000000F) +#define MMU_MMU_FAULT_SELECT_MMU_FAULT_SELECT_SHIFT (0) + +#define MMU_PROTOCOL_FAULT_OFFSET (0x00A8) + +#define MMU_PROTOCOL_FAULT_FAULT_PAGE_BREAK_MASK (0x00000001) +#define MMU_PROTOCOL_FAULT_FAULT_PAGE_BREAK_SHIFT (0) + +#define MMU_PROTOCOL_FAULT_FAULT_WRITE_MASK (0x00000010) +#define MMU_PROTOCOL_FAULT_FAULT_WRITE_SHIFT (4) + +#define MMU_PROTOCOL_FAULT_FAULT_READ_MASK (0x00000020) +#define MMU_PROTOCOL_FAULT_FAULT_READ_SHIFT (5) + +#define MMU_TOTAL_READ_REQ_OFFSET (0x0100) + +#define MMU_TOTAL_READ_REQ_TOTAL_READ_REQ_MASK (0xFFFFFFFF) +#define MMU_TOTAL_READ_REQ_TOTAL_READ_REQ_SHIFT (0) + +#define MMU_TOTAL_WRITE_REQ_OFFSET (0x0104) + +#define MMU_TOTAL_WRITE_REQ_TOTAL_WRITE_REQ_MASK (0xFFFFFFFF) +#define MMU_TOTAL_WRITE_REQ_TOTAL_WRITE_REQ_SHIFT (0) + +#define MMU_READS_LESS_64_REQ_OFFSET (0x0108) + +#define MMU_READS_LESS_64_REQ_READS_LESS_64_REQ_MASK (0xFFFFFFFF) +#define MMU_READS_LESS_64_REQ_READS_LESS_64_REQ_SHIFT (0) + +#define MMU_WRITES_LESS_64_REQ_OFFSET (0x010C) + +#define MMU_WRITES_LESS_64_REQ_WRITES_LESS_64_REQ_MASK (0xFFFFFFFF) +#define MMU_WRITES_LESS_64_REQ_WRITES_LESS_64_REQ_SHIFT (0) + +#define MMU_EXT_CMD_STALL_OFFSET (0x0120) + +#define MMU_EXT_CMD_STALL_EXT_CMD_STALL_MASK (0xFFFFFFFF) +#define MMU_EXT_CMD_STALL_EXT_CMD_STALL_SHIFT (0) + +#define MMU_WRITE_REQ_STALL_OFFSET (0x0124) + +#define MMU_WRITE_REQ_STALL_WRITE_REQ_STALL_MASK (0xFFFFFFFF) +#define MMU_WRITE_REQ_STALL_WRITE_REQ_STALL_SHIFT (0) + +#define MMU_MMU_MISS_STALL_OFFSET (0x0128) + +#define MMU_MMU_MISS_STALL_MMU_MISS_STALL_MASK (0xFFFFFFFF) +#define MMU_MMU_MISS_STALL_MMU_MISS_STALL_SHIFT (0) + +#define MMU_ADDRESS_STALL_OFFSET (0x012C) + +#define MMU_ADDRESS_STALL_ADDRESS_STALL_MASK (0xFFFFFFFF) +#define MMU_ADDRESS_STALL_ADDRESS_STALL_SHIFT (0) + +#define MMU_TAG_STALL_OFFSET (0x0130) + +#define MMU_TAG_STALL_TAG_STALL_MASK (0xFFFFFFFF) +#define MMU_TAG_STALL_TAG_STALL_SHIFT (0) + +#define MMU_PEAK_READ_OUTSTANDING_OFFSET (0x0140) + +#define MMU_PEAK_READ_OUTSTANDING_PEAK_TAG_OUTSTANDING_MASK (0x000003FF) +#define MMU_PEAK_READ_OUTSTANDING_PEAK_TAG_OUTSTANDING_SHIFT (0) + +#define MMU_PEAK_READ_OUTSTANDING_PEAK_READ_LATENCY_MASK (0xFFFF0000) +#define MMU_PEAK_READ_OUTSTANDING_PEAK_READ_LATENCY_SHIFT (16) + +#define MMU_AVERAGE_READ_LATENCY_OFFSET (0x0144) + +#define MMU_AVERAGE_READ_LATENCY_AVERAGE_READ_LATENCY_MASK (0xFFFFFFFF) +#define MMU_AVERAGE_READ_LATENCY_AVERAGE_READ_LATENCY_SHIFT (0) + +#define MMU_STATISTICS_CONTROL_OFFSET (0x0160) + +#define MMU_STATISTICS_CONTROL_BANDWIDTH_STATS_INIT_MASK (0x00000001) +#define MMU_STATISTICS_CONTROL_BANDWIDTH_STATS_INIT_SHIFT (0) + +#define MMU_STATISTICS_CONTROL_STALL_STATS_INIT_MASK (0x00000002) +#define MMU_STATISTICS_CONTROL_STALL_STATS_INIT_SHIFT (1) + +#define MMU_STATISTICS_CONTROL_LATENCY_STATS_INIT_MASK (0x00000004) +#define MMU_STATISTICS_CONTROL_LATENCY_STATS_INIT_SHIFT (2) + +#define MMU_MMU_VERSION_OFFSET (0x01D0) + +#define MMU_MMU_VERSION_MMU_MAJOR_REV_MASK (0x00FF0000) +#define MMU_MMU_VERSION_MMU_MAJOR_REV_SHIFT (16) + +#define MMU_MMU_VERSION_MMU_MINOR_REV_MASK (0x0000FF00) +#define MMU_MMU_VERSION_MMU_MINOR_REV_SHIFT (8) + +#define MMU_MMU_VERSION_MMU_MAINT_REV_MASK (0x000000FF) +#define MMU_MMU_VERSION_MMU_MAINT_REV_SHIFT (0) + +#define MMU_BYTE_SIZE (0x01D4) + +#endif From patchwork Fri Jun 7 13:28:31 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Devarsh Thakkar X-Patchwork-Id: 802500 Received: from fllv0015.ext.ti.com (fllv0015.ext.ti.com [198.47.19.141]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EED7D1946C6; Fri, 7 Jun 2024 13:28:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.47.19.141 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717766921; cv=none; b=aY40gOlvb1avqJZhT17eSdWS1bmxWmMC3wcH4LOzNxFexAfHgVJMMi/fTsA/Z8TdmTU2t1gAtAx1adMaJjIzZEOtaE99mixHgLR9Kjz9TWyrCxHCX8F818U+UG8flu/Rg8nsw6BDUKmeEvq1O/3AW8C1/iw0yeSOlRX0DXncBuw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717766921; c=relaxed/simple; bh=9YJDgD1sUF9wLiqDz96LWHNWgihyqNTKefm3EPo+PYg=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ur8CeR6Qpi7OFhkGHjP0Axx20vqUApLjGRsyLqCk3jbqpAGEWvf8MPUMJOJtpDyIeDpgMZmNcgcUqjfyfH8T5Z6NcX4LJiqcnvortL8SCGCZL0LeApz3WK5Okzw2/LkdheUgTTKPB0n6sHarR1fyEa5wFy2mfLNL6gDHWNEGpHI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com; spf=pass smtp.mailfrom=ti.com; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b=GuIyLith; arc=none smtp.client-ip=198.47.19.141 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ti.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="GuIyLith" Received: from lelv0265.itg.ti.com ([10.180.67.224]) by fllv0015.ext.ti.com (8.15.2/8.15.2) with ESMTP id 457DSXkT089042; Fri, 7 Jun 2024 08:28:33 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1717766913; bh=a2o0W9ZTFF+lA1Bhtoj/rJ7TGEn+u+N/UnDDrxbd6ck=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=GuIyLithFAkqa9SUjr139gcXjCGvpm9z9DYpALlWRGFiCCpE6+komDIsOfqmVGQyk TtY+Rlmf5hQymogKzDDfaQ0odpCjtj/V2BGapqFvib6lmvA6h5qZ1zNRrgg6EaB3cj UvtWWjCUNsN7gm9/hI5GOMssSP72z/1Nrj5Vklnw= Received: from DFLE108.ent.ti.com (dfle108.ent.ti.com [10.64.6.29]) by lelv0265.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 457DSX1S013748 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 7 Jun 2024 08:28:33 -0500 Received: from DFLE114.ent.ti.com (10.64.6.35) by DFLE108.ent.ti.com (10.64.6.29) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.23; Fri, 7 Jun 2024 08:28:33 -0500 Received: from lelvsmtp5.itg.ti.com (10.180.75.250) by DFLE114.ent.ti.com (10.64.6.35) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.23 via Frontend Transport; Fri, 7 Jun 2024 08:28:33 -0500 Received: from localhost (ti.dhcp.ti.com [172.24.227.95] (may be forged)) by lelvsmtp5.itg.ti.com (8.15.2/8.15.2) with ESMTP id 457DSWfN038953; Fri, 7 Jun 2024 08:28:32 -0500 From: Devarsh Thakkar To: , , , , , CC: , , , , , , , , , , , , Subject: [PATCH v13 03/13] media: v4l2-jpeg: Export reference quantization and huffman tables Date: Fri, 7 Jun 2024 18:58:31 +0530 Message-ID: <20240607132831.3551333-1-devarsht@ti.com> X-Mailer: git-send-email 2.39.1 In-Reply-To: <20240607131900.3535250-1-devarsht@ti.com> References: <20240607131900.3535250-1-devarsht@ti.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Export reference quantization and huffman tables as provided in ITU-T.81 so that they can be re-used by other JPEG drivers. These are example tables provided in ITU-T.81 as reference tables and the JPEG encoders are free to use either these or their own proprietary tables. Also add necessary prefixes to be used for huffman tables in global header file. Signed-off-by: Devarsh Thakkar --- V13: Fix smatch/sparse related below warning by using static global variable for arrays: Logs: +drivers/media/v4l2-core/v4l2-jpeg.c: warning: symbol 'luma_qt' was not declared. Should it be static? +drivers/media/v4l2-core/v4l2-jpeg.c: warning: symbol 'chroma_qt' was not declared. Should it be static? +drivers/media/v4l2-core/v4l2-jpeg.c: warning: symbol 'zigzag' was not declared. Should it be static? +drivers/media/v4l2-core/v4l2-jpeg.c: warning: symbol 'luma_dc_ht' was not declared. Should it be static? +drivers/media/v4l2-core/v4l2-jpeg.c: warning: symbol 'luma_ac_ht' was not declared. Should it be static? +drivers/media/v4l2-core/v4l2-jpeg.c: warning: symbol 'chroma_dc_ht' was not declared. Should it be static? +drivers/media/v4l2-core/v4l2-jpeg.c: warning: symbol 'chroma_ac_ht' was not declared. Should it be static?" V12: Fix html-doc warnings by removing * from args V11: No change V10: Add description for new macros introduced in this patchset V1->V9: No change (Patch introduced in V7) drivers/media/v4l2-core/v4l2-jpeg.c | 162 +++++++++++++++++++++++++++- include/media/v4l2-jpeg.h | 28 +++++ 2 files changed, 189 insertions(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/v4l2-jpeg.c b/drivers/media/v4l2-core/v4l2-jpeg.c index 94435a7b6816..bd6305c92e0e 100644 --- a/drivers/media/v4l2-core/v4l2-jpeg.c +++ b/drivers/media/v4l2-core/v4l2-jpeg.c @@ -16,7 +16,7 @@ #include #include -MODULE_DESCRIPTION("V4L2 JPEG header parser helpers"); +MODULE_DESCRIPTION("V4L2 JPEG helpers"); MODULE_AUTHOR("Philipp Zabel "); MODULE_LICENSE("GPL"); @@ -52,6 +52,115 @@ MODULE_LICENSE("GPL"); #define COM 0xfffe /* comment */ #define TEM 0xff01 /* temporary */ +/* Luma and chroma qp tables to achieve 50% compression quality + * This is as per example in Annex K.1 of ITU-T.81 + */ +static const u8 luma_qt[] = { + 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 56, 68, 109, 103, 77, + 24, 35, 55, 64, 81, 104, 113, 92, + 49, 64, 78, 87, 103, 121, 120, 101, + 72, 92, 95, 98, 112, 100, 103, 99 +}; + +static const u8 chroma_qt[] = { + 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 +}; + +/* Zigzag scan pattern */ +static const u8 zigzag[] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63 +}; + +/* + * Contains the data that needs to be sent in the marker segment of an + * interchange format JPEG stream or an abbreviated format table specification + * data stream. Specifies the huffman table used for encoding the luminance DC + * coefficient differences. The table represents Table K.3 of ITU-T.81 + */ +static const u8 luma_dc_ht[] = { + 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B +}; + +/* + * Contains the data that needs to be sent in the marker segment of an + * interchange format JPEG stream or an abbreviated format table specification + * data stream. Specifies the huffman table used for encoding the luminance AC + * coefficients. The table represents Table K.5 of ITU-T.81 + */ +static const u8 luma_ac_ht[] = { + 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, + 0x00, 0x00, 0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, + 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, + 0x81, 0x91, 0xA1, 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, + 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17, 0x18, 0x19, 0x1A, + 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, + 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x83, 0x84, 0x85, + 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, + 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, + 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, + 0xD9, 0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, + 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA +}; + +/* + * Contains the data that needs to be sent in the marker segment of an interchange format JPEG + * stream or an abbreviated format table specification data stream. + * Specifies the huffman table used for encoding the chrominance DC coefficient differences. + * The table represents Table K.4 of ITU-T.81 + */ +static const u8 chroma_dc_ht[] = { + 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B +}; + +/* + * Contains the data that needs to be sent in the marker segment of an + * interchange format JPEG stream or an abbreviated format table specification + * data stream. Specifies the huffman table used for encoding the chrominance + * AC coefficients. The table represents Table K.6 of ITU-T.81 + */ +static const u8 chroma_ac_ht[] = { + 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, + 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, + 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, + 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, + 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, + 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, + 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, + 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, + 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, + 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, + 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, + 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA +}; + /** * struct jpeg_stream - JPEG byte stream * @curr: current position in stream @@ -675,3 +784,54 @@ int v4l2_jpeg_parse_huffman_tables(void *buf, size_t len, return jpeg_parse_huffman_tables(&stream, huffman_tables); } EXPORT_SYMBOL_GPL(v4l2_jpeg_parse_huffman_tables); + +/** + * v4l2_jpeg_get_reference_quantization_tables - Get reference quantization + * tables as defined in ITU-T.81 + * @ref_luma_qt: Output variable pointing to luma quantization table + * @ref_chroma_qt: Output variable pointing to chroma quantization table + */ +void v4l2_jpeg_get_reference_quantization_tables(const u8 **ref_luma_qt, const + u8 **ref_chroma_qt) +{ + if (ref_luma_qt) + *ref_luma_qt = luma_qt; + if (ref_chroma_qt) + *ref_chroma_qt = chroma_qt; +} +EXPORT_SYMBOL_GPL(v4l2_jpeg_get_reference_quantization_tables); + +/** + * v4l2_jpeg_get_zig_zag_scan - Get zigzag scan table as defined in ITU-T.81 + * @ref_zigzag: Output variable pointing to zigzag scan table + */ +void v4l2_jpeg_get_zig_zag_scan(const u8 **ref_zigzag) +{ + if (ref_zigzag) + *ref_zigzag = zigzag; +} +EXPORT_SYMBOL_GPL(v4l2_jpeg_get_zig_zag_scan); + +/** + * v4l2_jpeg_get_reference_huffman_tables - Get reference huffman tables as + * defined in ITU-T.81 + * @ref_luma_dc_ht : Output variable pointing to huffman table for luma DC + * @ref_luma_ac_ht : Output variable pointing to huffman table for luma AC + * @ref_chroma_dc_ht : Output variable pointing to huffman table for chroma DC + * @ref_chroma_ac_ht : Output variable pointing to huffman table for chroma AC + */ +void v4l2_jpeg_get_reference_huffman_tables(const u8 **ref_luma_dc_ht, + const u8 **ref_luma_ac_ht, + const u8 **ref_chroma_dc_ht, + const u8 **ref_chroma_ac_ht) +{ + if (ref_luma_dc_ht) + *ref_luma_dc_ht = luma_dc_ht; + if (ref_luma_ac_ht) + *ref_luma_ac_ht = luma_ac_ht; + if (ref_chroma_dc_ht) + *ref_chroma_dc_ht = chroma_dc_ht; + if (ref_chroma_ac_ht) + *ref_chroma_ac_ht = chroma_ac_ht; +} +EXPORT_SYMBOL_GPL(v4l2_jpeg_get_reference_huffman_tables); diff --git a/include/media/v4l2-jpeg.h b/include/media/v4l2-jpeg.h index 2dba843ce3bd..b470bbffb73f 100644 --- a/include/media/v4l2-jpeg.h +++ b/include/media/v4l2-jpeg.h @@ -14,6 +14,30 @@ #define V4L2_JPEG_MAX_COMPONENTS 4 #define V4L2_JPEG_MAX_TABLES 4 +/* + * Prefixes used to generate huffman table class and destination identifiers as + * described below: + * + * V4L2_JPEG_LUM_HT | V4L2_JPEG_DC_HT : Prefix for Luma DC coefficients + * huffman table + * V4L2_JPEG_LUM_HT | V4L2_JPEG_AC_HT : Prefix for Luma AC coefficients + * huffman table + * V4L2_JPEG_CHR_HT | V4L2_JPEG_DC_HT : Prefix for Chroma DC coefficients + * huffman table + * V4L2_JPEG_CHR_HT | V4L2_JPEG_AC_HT : Prefix for Chroma AC coefficients + * huffman table + */ +#define V4L2_JPEG_LUM_HT 0x00 +#define V4L2_JPEG_CHR_HT 0x01 +#define V4L2_JPEG_DC_HT 0x00 +#define V4L2_JPEG_AC_HT 0x10 + +/* Length of reference huffman tables as provided in Table K.3 of ITU-T.81 */ +#define V4L2_JPEG_REF_HT_AC_LEN 178 +#define V4L2_JPEG_REF_HT_DC_LEN 28 + +/* Array size for 8x8 block of samples or DCT coefficient */ +#define V4L2_JPEG_PIXELS_IN_BLOCK 64 /** * struct v4l2_jpeg_reference - reference into the JPEG buffer @@ -154,4 +178,8 @@ int v4l2_jpeg_parse_quantization_tables(void *buf, size_t len, u8 precision, int v4l2_jpeg_parse_huffman_tables(void *buf, size_t len, struct v4l2_jpeg_reference *huffman_tables); +void v4l2_jpeg_get_reference_quantization_tables(const u8 **luma_qt, const u8 **chroma_qt); +void v4l2_jpeg_get_zig_zag_scan(const u8 **zigzag); +void v4l2_jpeg_get_reference_huffman_tables(const u8 **luma_dc_ht, const u8 **luma_ac_ht, + const u8 **chroma_dc_ht, const u8 **chroma_ac_ht); #endif From patchwork Fri Jun 7 13:29:01 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Devarsh Thakkar X-Patchwork-Id: 802756 Received: from lelv0143.ext.ti.com (lelv0143.ext.ti.com [198.47.23.248]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C9AFB194AC6; Fri, 7 Jun 2024 13:29:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.47.23.248 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717766964; cv=none; b=qXoOBr6d7+SyMVasn03jNirFs8jjRPCvNN36Xtoh+UXjCCzeX9Uhuv3E1EbEKzi/UcgxSw51x3wV+vBa4MmEiBy86wRqTB32TGgOLdbGlYb/n1nTuVqNDG0YKnmdl169vEtUbnS2JUE8IYiB3H10/bwj7tuO6h3poNGdagMvAng= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717766964; c=relaxed/simple; bh=z5y2B1JAfULyz/eK3dGfFNHOH8mN/la9z22S6Ay0pQ0=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=tWWsuiHU0Fs1ZTOuCw1/Y7lJEmqVu4PSxKLT4VAJrRJfriirXBgBa1YGV9aisWQKHX+eQkvMtVlSyTZXo8YA1TFSRqSql/p2i0ZCF8Jt6eyHraymNXszFfKwBNB3r5Ne5IC0I6FudhSCbPqxG5YuUBcJQw1q1ylShn9ybA3jhWI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com; spf=pass smtp.mailfrom=ti.com; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b=NwdDlXxo; arc=none smtp.client-ip=198.47.23.248 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ti.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="NwdDlXxo" Received: from fllv0035.itg.ti.com ([10.64.41.0]) by lelv0143.ext.ti.com (8.15.2/8.15.2) with ESMTP id 457DT3h8085999; Fri, 7 Jun 2024 08:29:03 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1717766943; bh=FqWdCWfJ5E0cE/02m7Qc63fVHLLQLLlM3Z750/UZJ6g=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=NwdDlXxoEUBnybM9NnWYIVc2Y2xmjF55dQZp9AgekpF7cImDGNPwqTZ889egLGlku daMg0ib4xnohBVNM7M54y+OWWe9EnXSSE8cFeGIHDlKbGkXhT1+A4M8EbglXbDy56Z y5V5O3RHkNTg6xpN6DP+yu+Gb4CaRIzP4nFzEfAc= Received: from DFLE109.ent.ti.com (dfle109.ent.ti.com [10.64.6.30]) by fllv0035.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 457DT3v1068419 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 7 Jun 2024 08:29:03 -0500 Received: from DFLE104.ent.ti.com (10.64.6.25) by DFLE109.ent.ti.com (10.64.6.30) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.23; Fri, 7 Jun 2024 08:29:03 -0500 Received: from lelvsmtp6.itg.ti.com (10.180.75.249) by DFLE104.ent.ti.com (10.64.6.25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.23 via Frontend Transport; Fri, 7 Jun 2024 08:29:03 -0500 Received: from localhost (ti.dhcp.ti.com [172.24.227.95] (may be forged)) by lelvsmtp6.itg.ti.com (8.15.2/8.15.2) with ESMTP id 457DT2LT111547; Fri, 7 Jun 2024 08:29:02 -0500 From: Devarsh Thakkar To: , , , , , , , , CC: , , , , , , , , , , , , Subject: [PATCH v13 04/13] media: Documentation: Document v4l2-jpeg helper functions Date: Fri, 7 Jun 2024 18:59:01 +0530 Message-ID: <20240607132901.3552233-1-devarsht@ti.com> X-Mailer: git-send-email 2.39.1 In-Reply-To: <20240607131900.3535250-1-devarsht@ti.com> References: <20240607131900.3535250-1-devarsht@ti.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Enable documentation for v4l2-jpeg header related helper functions which are useful for parsing jpeg files while decoding or creating jpeg headers while encoding. Signed-off-by: Devarsh Thakkar --- V2->V13: No change (patch introduced in v12) Documentation/driver-api/media/v4l2-core.rst | 1 + Documentation/driver-api/media/v4l2-jpeg.rst | 10 ++++++++++ 2 files changed, 11 insertions(+) create mode 100644 Documentation/driver-api/media/v4l2-jpeg.rst diff --git a/Documentation/driver-api/media/v4l2-core.rst b/Documentation/driver-api/media/v4l2-core.rst index 58cba831ade5..ad987c34ad2a 100644 --- a/Documentation/driver-api/media/v4l2-core.rst +++ b/Documentation/driver-api/media/v4l2-core.rst @@ -26,3 +26,4 @@ Video4Linux devices v4l2-tuner v4l2-common v4l2-tveeprom + v4l2-jpeg diff --git a/Documentation/driver-api/media/v4l2-jpeg.rst b/Documentation/driver-api/media/v4l2-jpeg.rst new file mode 100644 index 000000000000..af3bc52f865b --- /dev/null +++ b/Documentation/driver-api/media/v4l2-jpeg.rst @@ -0,0 +1,10 @@ +.. SPDX-License-Identifier: GPL-2.0 + +V4L2 JPEG header related functions and data structures +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. kernel-doc:: include/media/v4l2-jpeg.h + :internal: + +.. kernel-doc:: drivers/media/v4l2-core/v4l2-jpeg.c + :export: From patchwork Fri Jun 7 13:29:23 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Devarsh Thakkar X-Patchwork-Id: 802499 Received: from fllv0015.ext.ti.com (fllv0015.ext.ti.com [198.47.19.141]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 090111946DF; Fri, 7 Jun 2024 13:29:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.47.19.141 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717766980; cv=none; b=S/YqmUL2PwvdWVDeQIllplwgqAFeENU4rxIL9rO9/R9HQ+pVX18e2le4lfwa35Z+Y6XaF+R9S0TSHCSEZnGzpSKlsHUfZfNOe8fpSqsDL3yN+8AU1LYRp4QemD9Zx983LWbUTJW2ZTk1E0An4EA5iZYsbLFkc9+L5japCzie+44= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717766980; c=relaxed/simple; bh=IIkZAxNAAFtD/Pdw/NNJRbIhM0yr++RFhW2EoOerCQM=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=TMayymCt1aMfG0h3b9KGIBdspLlfB5l7KCoq95/L8qKbou4uu9ykWkFRuSP9uNlt80q5Y97fhPCCS/BKgVotw0uFqcyrqlgU7HdTf6TM+CUWcGod+UDSHEKxqCWns3tvM8pr0Sqjd95MAfRyf9s0ssblUEX9sKIm2HzflcF1LsY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com; spf=pass smtp.mailfrom=ti.com; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b=l88Og0M7; arc=none smtp.client-ip=198.47.19.141 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ti.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="l88Og0M7" Received: from fllv0035.itg.ti.com ([10.64.41.0]) by fllv0015.ext.ti.com (8.15.2/8.15.2) with ESMTP id 457DTPen089613; Fri, 7 Jun 2024 08:29:25 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1717766965; bh=ysUV6AF5jAzAQc6Gn/WVBo4RP7R/u8UQMBQ+AL+STKo=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=l88Og0M72N4bFWSRzoTwWBPZ3REkI6qBJ8IQ1UVVxsdhuLMlwIF26W9ia+oEBr+m1 pzvjauNKDU1iDGehvJqqe7EPwUXRMi304ml4dc48d0VVDtstTYVwfKcKZqPTQhYwMQ LoMb2Kg3CbslxSRAy2G4XDPWUUzHwcFIVB2Ewal4= Received: from DLEE112.ent.ti.com (dlee112.ent.ti.com [157.170.170.23]) by fllv0035.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 457DTPc0068629 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 7 Jun 2024 08:29:25 -0500 Received: from DLEE101.ent.ti.com (157.170.170.31) by DLEE112.ent.ti.com (157.170.170.23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.23; Fri, 7 Jun 2024 08:29:24 -0500 Received: from lelvsmtp6.itg.ti.com (10.180.75.249) by DLEE101.ent.ti.com (157.170.170.31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.23 via Frontend Transport; Fri, 7 Jun 2024 08:29:24 -0500 Received: from localhost (ti.dhcp.ti.com [172.24.227.95] (may be forged)) by lelvsmtp6.itg.ti.com (8.15.2/8.15.2) with ESMTP id 457DTOTr111920; Fri, 7 Jun 2024 08:29:24 -0500 From: Devarsh Thakkar To: , , , , , CC: , , , , , , , , , , , , , , , Subject: [PATCH v13 05/13] media: imagination: Use exported tables from v4l2-jpeg core Date: Fri, 7 Jun 2024 18:59:23 +0530 Message-ID: <20240607132923.3552925-1-devarsht@ti.com> X-Mailer: git-send-email 2.39.1 In-Reply-To: <20240607131900.3535250-1-devarsht@ti.com> References: <20240607131900.3535250-1-devarsht@ti.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Use exported huffman and quantization tables from v4l2-jpeg core library. Signed-off-by: Devarsh Thakkar --- V1->V13 (No change, patch introduced in V7) drivers/media/platform/imagination/Kconfig | 1 + .../platform/imagination/e5010-jpeg-enc.c | 140 +++--------------- 2 files changed, 20 insertions(+), 121 deletions(-) diff --git a/drivers/media/platform/imagination/Kconfig b/drivers/media/platform/imagination/Kconfig index d8d79266ad5d..7139ae22219b 100644 --- a/drivers/media/platform/imagination/Kconfig +++ b/drivers/media/platform/imagination/Kconfig @@ -5,6 +5,7 @@ config VIDEO_E5010_JPEG_ENC select VIDEOBUF2_DMA_CONTIG select VIDEOBUF2_VMALLOC select V4L2_MEM2MEM_DEV + select V4L2_JPEG_HELPER help This is a video4linux2 M2M driver for Imagination E5010 JPEG encoder, which supports JPEG and MJPEG baseline encoding of YUV422 and YUV420 diff --git a/drivers/media/platform/imagination/e5010-jpeg-enc.c b/drivers/media/platform/imagination/e5010-jpeg-enc.c index 17b8ec306ffc..4b6fbe99d5ff 100644 --- a/drivers/media/platform/imagination/e5010-jpeg-enc.c +++ b/drivers/media/platform/imagination/e5010-jpeg-enc.c @@ -32,116 +32,6 @@ #include "e5010-jpeg-enc.h" #include "e5010-jpeg-enc-hw.h" -/* Luma and chroma qp table to achieve 50% compression quality - * This is as per example in Annex K.1 of ITU-T.81 - */ -static const u8 luma_q_table[64] = { - 16, 11, 10, 16, 24, 40, 51, 61, - 12, 12, 14, 19, 26, 58, 60, 55, - 14, 13, 16, 24, 40, 57, 69, 56, - 14, 17, 22, 29, 51, 87, 80, 62, - 18, 22, 37, 56, 68, 109, 103, 77, - 24, 35, 55, 64, 81, 104, 113, 92, - 49, 64, 78, 87, 103, 121, 120, 101, - 72, 92, 95, 98, 112, 100, 103, 99 -}; - -static const u8 chroma_q_table[64] = { - 17, 18, 24, 47, 99, 99, 99, 99, - 18, 21, 26, 66, 99, 99, 99, 99, - 24, 26, 56, 99, 99, 99, 99, 99, - 47, 66, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99 -}; - -/* Zigzag scan pattern */ -static const u8 zigzag[64] = { - 0, 1, 8, 16, 9, 2, 3, 10, - 17, 24, 32, 25, 18, 11, 4, 5, - 12, 19, 26, 33, 40, 48, 41, 34, - 27, 20, 13, 6, 7, 14, 21, 28, - 35, 42, 49, 56, 57, 50, 43, 36, - 29, 22, 15, 23, 30, 37, 44, 51, - 58, 59, 52, 45, 38, 31, 39, 46, - 53, 60, 61, 54, 47, 55, 62, 63 -}; - -/* - * Contains the data that needs to be sent in the marker segment of an interchange format JPEG - * stream or an abbreviated format table specification data stream. - * Specifies the huffman table used for encoding the luminance DC coefficient differences. - * The table represents Table K.3 of ITU-T.81 - */ -static const u8 luma_dc_table[] = { - 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B -}; - -/* - * Contains the data that needs to be sent in the marker segment of an interchange format JPEG - * stream or an abbreviated format table specification data stream. - * Specifies the huffman table used for encoding the luminance AC coefficients. - * The table represents Table K.5 of ITU-T.81 - */ -static const u8 luma_ac_table[] = { - 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, - 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, - 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, - 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, - 0xD1, 0xF0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25, - 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, - 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, - 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x83, - 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, - 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, - 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, - 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, - 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA -}; - -/* - * Contains the data that needs to be sent in the marker segment of an interchange format JPEG - * stream or an abbreviated format table specification data stream. - * Specifies the huffman table used for encoding the chrominance DC coefficient differences. - * The table represents Table K.4 of ITU-T.81 - */ -static const u8 chroma_dc_table[] = { - 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B -}; - -/* - * Contains the data that needs to be sent in the marker segment of an interchange format JPEG - * stream or an abbreviated format table specification data stream. - * Specifies the huffman table used for encoding the chrominance AC coefficients. - * The table represents Table K.6 of ITU-T.81 - */ -static const u8 chroma_ac_table[] = { - 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, - 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, - 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, - 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, - 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, - 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, - 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, - 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, - 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, - 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, - 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, - 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, - 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA -}; - -#define JPEG_LUM_HT 0x00 -#define JPEG_CHR_HT 0x01 -#define JPEG_DC_HT 0x00 -#define JPEG_AC_HT 0x10 - /* forward declarations */ static const struct of_device_id e5010_of_match[]; @@ -270,6 +160,9 @@ static void calculate_qp_tables(struct e5010_context *ctx) { long long luminosity, contrast; int quality, i; + const u8 *luma_q_table, *chroma_q_table; + + v4l2_jpeg_get_reference_quantization_tables(&luma_q_table, &chroma_q_table); quality = 50 - ctx->quality; @@ -281,7 +174,7 @@ static void calculate_qp_tables(struct e5010_context *ctx) contrast *= INCREASE; } - for (i = 0; i < ARRAY_SIZE(luma_q_table); i++) { + for (i = 0; i < V4L2_JPEG_PIXELS_IN_BLOCK; i++) { long long delta = chroma_q_table[i] * contrast + luminosity; int val = (int)(chroma_q_table[i] + delta); @@ -927,41 +820,46 @@ static void encode_marker_segment(struct e5010_context *ctx, void *addr, unsigne { u8 *buffer = (u8 *)addr; int i; + const u8 *luma_dc_table, *chroma_dc_table, *luma_ac_table, *chroma_ac_table, *zigzag; + + v4l2_jpeg_get_reference_huffman_tables(&luma_dc_table, &luma_ac_table, &chroma_dc_table, + &chroma_ac_table); + v4l2_jpeg_get_zig_zag_scan(&zigzag); header_write(ctx, buffer, offset, 2, START_OF_IMAGE); header_write(ctx, buffer, offset, 2, DQT_MARKER); header_write(ctx, buffer, offset, 3, LQPQ << 4); - for (i = 0; i < PELS_IN_BLOCK; i++) + for (i = 0; i < V4L2_JPEG_PIXELS_IN_BLOCK; i++) header_write(ctx, buffer, offset, 1, ctx->luma_qp[zigzag[i]]); header_write(ctx, buffer, offset, 2, DQT_MARKER); header_write(ctx, buffer, offset, 3, (LQPQ << 4) | 1); - for (i = 0; i < PELS_IN_BLOCK; i++) + for (i = 0; i < V4L2_JPEG_PIXELS_IN_BLOCK; i++) header_write(ctx, buffer, offset, 1, ctx->chroma_qp[zigzag[i]]); /* Huffman tables */ header_write(ctx, buffer, offset, 2, DHT_MARKER); header_write(ctx, buffer, offset, 2, LH_DC); - header_write(ctx, buffer, offset, 1, JPEG_LUM_HT | JPEG_DC_HT); - for (i = 0 ; i < ARRAY_SIZE(luma_dc_table); i++) + header_write(ctx, buffer, offset, 1, V4L2_JPEG_LUM_HT | V4L2_JPEG_DC_HT); + for (i = 0 ; i < V4L2_JPEG_REF_HT_DC_LEN; i++) header_write(ctx, buffer, offset, 1, luma_dc_table[i]); header_write(ctx, buffer, offset, 2, DHT_MARKER); header_write(ctx, buffer, offset, 2, LH_AC); - header_write(ctx, buffer, offset, 1, JPEG_LUM_HT | JPEG_AC_HT); - for (i = 0 ; i < ARRAY_SIZE(luma_ac_table); i++) + header_write(ctx, buffer, offset, 1, V4L2_JPEG_LUM_HT | V4L2_JPEG_AC_HT); + for (i = 0 ; i < V4L2_JPEG_REF_HT_AC_LEN; i++) header_write(ctx, buffer, offset, 1, luma_ac_table[i]); header_write(ctx, buffer, offset, 2, DHT_MARKER); header_write(ctx, buffer, offset, 2, LH_DC); - header_write(ctx, buffer, offset, 1, JPEG_CHR_HT | JPEG_DC_HT); - for (i = 0 ; i < ARRAY_SIZE(chroma_dc_table); i++) + header_write(ctx, buffer, offset, 1, V4L2_JPEG_CHR_HT | V4L2_JPEG_DC_HT); + for (i = 0 ; i < V4L2_JPEG_REF_HT_DC_LEN; i++) header_write(ctx, buffer, offset, 1, chroma_dc_table[i]); header_write(ctx, buffer, offset, 2, DHT_MARKER); header_write(ctx, buffer, offset, 2, LH_AC); - header_write(ctx, buffer, offset, 1, JPEG_CHR_HT | JPEG_AC_HT); - for (i = 0 ; i < ARRAY_SIZE(chroma_ac_table); i++) + header_write(ctx, buffer, offset, 1, V4L2_JPEG_CHR_HT | V4L2_JPEG_AC_HT); + for (i = 0 ; i < V4L2_JPEG_REF_HT_AC_LEN; i++) header_write(ctx, buffer, offset, 1, chroma_ac_table[i]); } From patchwork Fri Jun 7 13:30:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Devarsh Thakkar X-Patchwork-Id: 802755 Received: from fllv0016.ext.ti.com (fllv0016.ext.ti.com [198.47.19.142]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4A32D13D2A0; Fri, 7 Jun 2024 13:30:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.47.19.142 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717767027; cv=none; b=GIgtAIIyeRayfbctbmIY7gd7WtjlpBL8oWWfwwRAjJRyqPvYXte/Daj9oAhMus2f7oir8+Aps9A57unTkluhjfw87QsOMnX4pUov/3MBFKl/pC4RoE8KrQIGxF4GHKG6OGsZQgA+p6aH6H/Lv9lseDMhgfRK+l3984ZH4P4VFaI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717767027; c=relaxed/simple; bh=6pVcRftZ9US+s4fX7bTowE7emRoXvyijU38vyJ6yZ08=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=S6r5VOYjdw3QX45c9FkkS3DTnJF7+My+4ntcNeXZueiqYe+ze9H7lxSWU1cRF5Dm2dk4CzloPBcYNhmKb3NpJ6V/uIqe/knc1TMkgFs7Nvx7hDjLVdJpb3dal9tI73vEMaCSwX93W1sv9xUVfIbku3AsKfYnjFR4dUvcj5278N8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com; spf=pass smtp.mailfrom=ti.com; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b=c5pmKRAr; arc=none smtp.client-ip=198.47.19.142 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ti.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="c5pmKRAr" Received: from lelv0265.itg.ti.com ([10.180.67.224]) by fllv0016.ext.ti.com (8.15.2/8.15.2) with ESMTP id 457DUAl3116698; Fri, 7 Jun 2024 08:30:10 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1717767010; bh=t/45uToTzvle1DU3dPZ6R7yriRkJXy54nbH9mTAodPM=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=c5pmKRArQajDX8WsB83Y4yfTry9PLmi7k8dqmP7wWOrMEbbImfnA/i4SuLE8PCl7v Rvs7ZyZPevCYZiM8ATCW4kYN9M3Ms4k+mPOu8Abg/MkBbBs2TPlDKV+pa5TfY/JUlw gi0bBJjiEgu0ojzHaxZ9nLwY+iJCrnHk3U7EKi6I= Received: from DLEE101.ent.ti.com (dlee101.ent.ti.com [157.170.170.31]) by lelv0265.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 457DUAuK015334 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 7 Jun 2024 08:30:10 -0500 Received: from DLEE100.ent.ti.com (157.170.170.30) by DLEE101.ent.ti.com (157.170.170.31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.23; Fri, 7 Jun 2024 08:30:10 -0500 Received: from lelvsmtp6.itg.ti.com (10.180.75.249) by DLEE100.ent.ti.com (157.170.170.30) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.23 via Frontend Transport; Fri, 7 Jun 2024 08:30:10 -0500 Received: from localhost (ti.dhcp.ti.com [172.24.227.95] (may be forged)) by lelvsmtp6.itg.ti.com (8.15.2/8.15.2) with ESMTP id 457DU9jD115084; Fri, 7 Jun 2024 08:30:10 -0500 From: Devarsh Thakkar To: , , , , , , , , CC: , , , , , , , , , , , , Subject: [PATCH v13 06/13] media: verisilicon : Use exported tables from v4l2-jpeg for hantro codec Date: Fri, 7 Jun 2024 19:00:08 +0530 Message-ID: <20240607133008.3554256-1-devarsht@ti.com> X-Mailer: git-send-email 2.39.1 In-Reply-To: <20240607131900.3535250-1-devarsht@ti.com> References: <20240607131900.3535250-1-devarsht@ti.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Use v4l2-jpeg core API to import reference quantization and huffman tables used for JPEG Encoding. Signed-off-by: Devarsh Thakkar Reviewed-by: Chen-Yu Tsai Acked-by: Nicolas Dufresne --- V11->V13: No change V10: Fix typo in commit message title V9: No change V8: Add Reviewed-by and Acked-by tags V1->V6 (No change, patch introduced in V7) --- drivers/media/platform/verisilicon/Kconfig | 1 + .../media/platform/verisilicon/hantro_jpeg.c | 128 ++---------------- 2 files changed, 15 insertions(+), 114 deletions(-) diff --git a/drivers/media/platform/verisilicon/Kconfig b/drivers/media/platform/verisilicon/Kconfig index 9a34d14c6e40..149d0b32c324 100644 --- a/drivers/media/platform/verisilicon/Kconfig +++ b/drivers/media/platform/verisilicon/Kconfig @@ -12,6 +12,7 @@ config VIDEO_HANTRO select VIDEOBUF2_VMALLOC select V4L2_MEM2MEM_DEV select V4L2_H264 + select V4L2_JPEG_HELPER select V4L2_VP9 help Support for the Hantro IP based Video Processing Units present on diff --git a/drivers/media/platform/verisilicon/hantro_jpeg.c b/drivers/media/platform/verisilicon/hantro_jpeg.c index d07b1b449b61..fa4e8ee92c05 100644 --- a/drivers/media/platform/verisilicon/hantro_jpeg.c +++ b/drivers/media/platform/verisilicon/hantro_jpeg.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "hantro_jpeg.h" #include "hantro.h" @@ -24,42 +25,6 @@ #define HUFF_CHROMA_DC_OFF 394 #define HUFF_CHROMA_AC_OFF 427 -/* Default tables from JPEG ITU-T.81 - * (ISO/IEC 10918-1) Annex K, tables K.1 and K.2 - */ -static const unsigned char luma_q_table[] = { - 0x10, 0x0b, 0x0a, 0x10, 0x18, 0x28, 0x33, 0x3d, - 0x0c, 0x0c, 0x0e, 0x13, 0x1a, 0x3a, 0x3c, 0x37, - 0x0e, 0x0d, 0x10, 0x18, 0x28, 0x39, 0x45, 0x38, - 0x0e, 0x11, 0x16, 0x1d, 0x33, 0x57, 0x50, 0x3e, - 0x12, 0x16, 0x25, 0x38, 0x44, 0x6d, 0x67, 0x4d, - 0x18, 0x23, 0x37, 0x40, 0x51, 0x68, 0x71, 0x5c, - 0x31, 0x40, 0x4e, 0x57, 0x67, 0x79, 0x78, 0x65, - 0x48, 0x5c, 0x5f, 0x62, 0x70, 0x64, 0x67, 0x63 -}; - -static const unsigned char chroma_q_table[] = { - 0x11, 0x12, 0x18, 0x2f, 0x63, 0x63, 0x63, 0x63, - 0x12, 0x15, 0x1a, 0x42, 0x63, 0x63, 0x63, 0x63, - 0x18, 0x1a, 0x38, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x2f, 0x42, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63 -}; - -static const unsigned char zigzag[] = { - 0, 1, 8, 16, 9, 2, 3, 10, - 17, 24, 32, 25, 18, 11, 4, 5, - 12, 19, 26, 33, 40, 48, 41, 34, - 27, 20, 13, 6, 7, 14, 21, 28, - 35, 42, 49, 56, 57, 50, 43, 36, - 29, 22, 15, 23, 30, 37, 44, 51, - 58, 59, 52, 45, 38, 31, 39, 46, - 53, 60, 61, 54, 47, 55, 62, 63 -}; - static const u32 hw_reorder[] = { 0, 8, 16, 24, 1, 9, 17, 25, 32, 40, 48, 56, 33, 41, 49, 57, @@ -71,73 +36,6 @@ static const u32 hw_reorder[] = { 38, 46, 54, 62, 39, 47, 55, 63 }; -/* Huffman tables are shared with CODA */ -static const unsigned char luma_dc_table[] = { - 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, -}; - -static const unsigned char chroma_dc_table[] = { - 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, -}; - -static const unsigned char luma_ac_table[] = { - 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, - 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d, - 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, - 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, - 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, - 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, - 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, - 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, - 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, - 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, - 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, - 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, - 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, - 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, - 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, - 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, - 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, - 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, - 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, - 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, - 0xf9, 0xfa, -}; - -static const unsigned char chroma_ac_table[] = { - 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, - 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, - 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, - 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, - 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, - 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, - 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, - 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, - 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, - 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, - 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, - 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, - 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, - 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, - 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, - 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, - 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, - 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, - 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, - 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, - 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, - 0xf9, 0xfa, -}; - /* For simplicity, we keep a pre-formatted JPEG header, * and we'll use fixed offsets to change the width, height * quantization tables, etc. @@ -291,10 +189,11 @@ jpeg_scale_quant_table(unsigned char *file_q_tab, const unsigned char *tab, int scale) { int i; + const u8 *zigzag; - BUILD_BUG_ON(ARRAY_SIZE(zigzag) != JPEG_QUANT_SIZE); BUILD_BUG_ON(ARRAY_SIZE(hw_reorder) != JPEG_QUANT_SIZE); + v4l2_jpeg_get_zig_zag_scan(&zigzag); for (i = 0; i < JPEG_QUANT_SIZE; i++) { file_q_tab[i] = jpeg_scale_qp(tab[zigzag[i]], scale); reordered_q_tab[i] = jpeg_scale_qp(tab[hw_reorder[i]], scale); @@ -304,6 +203,7 @@ jpeg_scale_quant_table(unsigned char *file_q_tab, static void jpeg_set_quality(struct hantro_jpeg_ctx *ctx) { int scale; + const u8 *luma_q_table, *chroma_q_table; /* * Non-linear scaling factor: @@ -314,21 +214,23 @@ static void jpeg_set_quality(struct hantro_jpeg_ctx *ctx) else scale = 200 - 2 * ctx->quality; - BUILD_BUG_ON(ARRAY_SIZE(luma_q_table) != JPEG_QUANT_SIZE); - BUILD_BUG_ON(ARRAY_SIZE(chroma_q_table) != JPEG_QUANT_SIZE); BUILD_BUG_ON(ARRAY_SIZE(ctx->hw_luma_qtable) != JPEG_QUANT_SIZE); BUILD_BUG_ON(ARRAY_SIZE(ctx->hw_chroma_qtable) != JPEG_QUANT_SIZE); + v4l2_jpeg_get_reference_quantization_tables(&luma_q_table, &chroma_q_table); jpeg_scale_quant_table(ctx->buffer + LUMA_QUANT_OFF, - ctx->hw_luma_qtable, luma_q_table, scale); + ctx->hw_luma_qtable, (const unsigned char *)luma_q_table, scale); jpeg_scale_quant_table(ctx->buffer + CHROMA_QUANT_OFF, - ctx->hw_chroma_qtable, chroma_q_table, scale); + ctx->hw_chroma_qtable, (const unsigned char *)chroma_q_table, scale); } void hantro_jpeg_header_assemble(struct hantro_jpeg_ctx *ctx) { char *buf = ctx->buffer; + const u8 *luma_dc_table, *chroma_dc_table, *luma_ac_table, *chroma_ac_table; + v4l2_jpeg_get_reference_huffman_tables(&luma_dc_table, &luma_ac_table, &chroma_dc_table, + &chroma_ac_table); memcpy(buf, hantro_jpeg_header, sizeof(hantro_jpeg_header)); @@ -337,12 +239,10 @@ void hantro_jpeg_header_assemble(struct hantro_jpeg_ctx *ctx) buf[WIDTH_OFF + 0] = ctx->width >> 8; buf[WIDTH_OFF + 1] = ctx->width; - memcpy(buf + HUFF_LUMA_DC_OFF, luma_dc_table, sizeof(luma_dc_table)); - memcpy(buf + HUFF_LUMA_AC_OFF, luma_ac_table, sizeof(luma_ac_table)); - memcpy(buf + HUFF_CHROMA_DC_OFF, chroma_dc_table, - sizeof(chroma_dc_table)); - memcpy(buf + HUFF_CHROMA_AC_OFF, chroma_ac_table, - sizeof(chroma_ac_table)); + memcpy(buf + HUFF_LUMA_DC_OFF, luma_dc_table, V4L2_JPEG_REF_HT_DC_LEN); + memcpy(buf + HUFF_LUMA_AC_OFF, luma_ac_table, V4L2_JPEG_REF_HT_AC_LEN); + memcpy(buf + HUFF_CHROMA_DC_OFF, chroma_dc_table, V4L2_JPEG_REF_HT_DC_LEN); + memcpy(buf + HUFF_CHROMA_AC_OFF, chroma_ac_table, V4L2_JPEG_REF_HT_AC_LEN); jpeg_set_quality(ctx); } From patchwork Fri Jun 7 13:30:31 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Devarsh Thakkar X-Patchwork-Id: 802498 Received: from fllv0016.ext.ti.com (fllv0016.ext.ti.com [198.47.19.142]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CFB1F1DFEB; Fri, 7 Jun 2024 13:30:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.47.19.142 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717767050; cv=none; b=dgLS1VLnGNUQav8zVKYMZ+RGjqi6iyaeXolx93tnO/IjfLHrOmIKHejdmgF5sPxJ5An4NqwJAbdLCjELAl1PMUGto254kZuQ/GR1u9DFbt4gD6IJVXCkZ8jE/Jed+kp009CLPof1RU1tqKsMU/ML6KPwy/D9xsrHifdDX/SLK+A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717767050; c=relaxed/simple; bh=E9WAN1nWyMYGyn40v9XuvkFgSu2QFIpFEvxOhHf71XA=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=u2wNzkXLWWE15/Ye5Tx1wwgajKUVHHuNKb1nlOPY477KlHGoosna3KPS0rWjikaQoHz3l+JonxZ++rFp3GO9AtASE+vAscTo4oK/2YI21kyjbTGsWpl/0zm1OE7rFIwiEEaqSIZayY1WjcclzSKQYoCkL0UhD8iwl+uMUEthY5E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com; spf=pass smtp.mailfrom=ti.com; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b=GwbeohZz; arc=none smtp.client-ip=198.47.19.142 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ti.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="GwbeohZz" Received: from lelv0265.itg.ti.com ([10.180.67.224]) by fllv0016.ext.ti.com (8.15.2/8.15.2) with ESMTP id 457DUXCS117000; Fri, 7 Jun 2024 08:30:33 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1717767033; bh=mQTpqKBioeHkJyoOLDE3kmEy90IWWpuUFK/eBuma05M=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=GwbeohZzXT/Qx3WJLtMsNtf+CdTPBD/KSDNf7LKx7Vr84eukY1OzPlndSVzH0UqyQ Pe4dQHvW3LblDGPLgeTOuOB/ArX48E7b183x+Ns5wEDQxESxaa2bL7voIUTSeAGPZe zHa/o6SexlXCjEdEZ6LYNjKYJaC86EHuo4baCxk0= Received: from DLEE104.ent.ti.com (dlee104.ent.ti.com [157.170.170.34]) by lelv0265.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 457DUXrB015667 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 7 Jun 2024 08:30:33 -0500 Received: from DLEE107.ent.ti.com (157.170.170.37) by DLEE104.ent.ti.com (157.170.170.34) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.23; Fri, 7 Jun 2024 08:30:33 -0500 Received: from lelvsmtp5.itg.ti.com (10.180.75.250) by DLEE107.ent.ti.com (157.170.170.37) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.23 via Frontend Transport; Fri, 7 Jun 2024 08:30:33 -0500 Received: from localhost (ti.dhcp.ti.com [172.24.227.95] (may be forged)) by lelvsmtp5.itg.ti.com (8.15.2/8.15.2) with ESMTP id 457DUWI6043730; Fri, 7 Jun 2024 08:30:32 -0500 From: Devarsh Thakkar To: , , , , , , , , , , , , , , CC: , , , , , , , , , , , , , , Subject: [PATCH v13 07/13] math.h: Add macros for rounding to closest value Date: Fri, 7 Jun 2024 19:00:31 +0530 Message-ID: <20240607133031.3554979-1-devarsht@ti.com> X-Mailer: git-send-email 2.39.1 In-Reply-To: <20240607131900.3535250-1-devarsht@ti.com> References: <20240607131900.3535250-1-devarsht@ti.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Add below rounding related macros: round_closest_up(x, y) : Rounds x to closest multiple of y where y is a power of 2, with a preference to round up in case two nearest values are possible. round_closest_down(x, y) : Rounds x to closest multiple of y where y is a power of 2, with a preference to round down in case two nearest values are possible. roundclosest(x, y) : Rounds x to closest multiple of y, this macro should generally be used only when y is not multiple of 2 as otherwise round_closest* macros should be used which are much faster. Examples: * round_closest_up(17, 4) = 16 * round_closest_up(15, 4) = 16 * round_closest_up(14, 4) = 16 * round_closest_down(17, 4) = 16 * round_closest_down(15, 4) = 16 * round_closest_down(14, 4) = 12 * roundclosest(21, 5) = 20 * roundclosest(19, 5) = 20 * roundclosest(17, 5) = 15 Signed-off-by: Devarsh Thakkar Acked-by: Andy Shevchenko --- NOTE: This patch is inspired from the Mentor Graphics IPU driver [1] which uses similar macro locally and which is updated in further patch in the series to use this generic macro instead along with other drivers having similar requirements. Link: https://elixir.bootlin.com/linux/v6.8.9/source/drivers/gpu/ipu-v3/ipu-image-convert.c#L480 [1] V13: - No change V12: - Add Acked-by V11: - Fix commenting style per review comments and remove extra whitespace V10: - Update example comment to fix formatting issues as observed with html docs V9: - No change V8: - Add new macro to round to nearest value for non-multiple of 2 - Update commit message as suggested: V1->V6 (No change, patch introduced in V7) include/linux/math.h | 63 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/include/linux/math.h b/include/linux/math.h index dd4152711de7..79e3dfda77fc 100644 --- a/include/linux/math.h +++ b/include/linux/math.h @@ -34,6 +34,52 @@ */ #define round_down(x, y) ((x) & ~__round_mask(x, y)) +/** + * round_closest_up - round closest to be multiple of specified value (which is + * power of 2) with preference to rounding up + * @x: the value to round + * @y: multiple to round closest to (must be a power of 2) + * + * Rounds @x to closest multiple of @y (which must be a power of 2). + * The value can be either rounded up or rounded down depending upon rounded + * value's closeness to the specified value. If there are two closest possible + * values, i.e. the difference between the specified value and it's rounded up + * and rounded down values is same then preference is given to rounded up + * value. + * + * To perform arbitrary rounding to closest value (not multiple of 2), use + * roundclosest(). + * + * Examples: + * * round_closest_up(17, 4) = 16 + * * round_closest_up(15, 4) = 16 + * * round_closest_up(14, 4) = 16 + */ +#define round_closest_up(x, y) round_down((x) + (y) / 2, (y)) + +/** + * round_closest_down - round closest to be multiple of specified value (which + * is power of 2) with preference to rounding down + * @x: the value to round + * @y: multiple to round closest to (must be a power of 2) + * + * Rounds @x to closest multiple of @y (which must be a power of 2). + * The value can be either rounded up or rounded down depending upon rounded + * value's closeness to the specified value. If there are two closest possible + * values, i.e. the difference between the specified value and it's rounded up + * and rounded down values is same then preference is given to rounded up + * value. + * + * To perform arbitrary rounding to closest value (not multiple of 2), use + * roundclosest(). + * + * Examples: + * * round_closest_down(17, 4) = 16 + * * round_closest_down(15, 4) = 16 + * * round_closest_down(14, 4) = 12 + */ +#define round_closest_down(x, y) round_up((x) - (y) / 2, (y)) + #define DIV_ROUND_UP __KERNEL_DIV_ROUND_UP #define DIV_ROUND_DOWN_ULL(ll, d) \ @@ -77,6 +123,23 @@ } \ ) +/** + * roundclosest - round to nearest multiple + * @x: the value to round + * @y: multiple to round nearest to + * + * Rounds @x to nearest multiple of @y. + * The rounded value can be greater than or less than @x depending + * upon it's nearness to @x. If @y will always be a power of 2, consider + * using the faster round_closest_up() or round_closest_down(). + * + * Examples: + * * roundclosest(21, 5) = 20 + * * roundclosest(19, 5) = 20 + * * roundclosest(17, 5) = 15 + */ +#define roundclosest(x, y) rounddown((x) + (y) / 2, (y)) + /* * Divide positive or negative dividend by positive or negative divisor * and round to closest integer. Result is undefined for negative From patchwork Fri Jun 7 13:30:52 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Devarsh Thakkar X-Patchwork-Id: 802754 Received: from lelv0143.ext.ti.com (lelv0143.ext.ti.com [198.47.23.248]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8864019414B; Fri, 7 Jun 2024 13:31:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.47.23.248 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717767072; cv=none; b=TSipNGrIdMZWnlU86HObfBiIyzblmVdBDHQmpA46YqnujPHUaTyFO+LY4DOcDgXaudGa1+WmhmlCUpKfg5lr9VAhk6C79zeq2j5FeHtjVpz59CZsBHO3NAyp+rkddXHSqozTEORg1d1jjVCjYQysddh7NlsszTOVXCijAEe6aW4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717767072; c=relaxed/simple; bh=FINJunvslvsDft6X0FCW9fIW4x9HDOR96bpphV+WFCY=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=XQ3BiFTMfur1//35lLaUKaOiNbxGacSbmM6W2pggg6Xfon1JoRTAKq/3gOMICpZgmo4QcHA3fdQ5waScBw4im/GCnUnI+G3Fku45f6llgXaLNySIyUowNREtyKOqrrWQym81+at2R53YpOqCkI/LEl6xwjoinjrS5dKHUR76Vho= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com; spf=pass smtp.mailfrom=ti.com; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b=kfm9fNc7; arc=none smtp.client-ip=198.47.23.248 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ti.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="kfm9fNc7" Received: from lelv0266.itg.ti.com ([10.180.67.225]) by lelv0143.ext.ti.com (8.15.2/8.15.2) with ESMTP id 457DUs0Q086595; Fri, 7 Jun 2024 08:30:54 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1717767054; bh=wT+sQQdkJtU/Yzp+KDhp78KwpzqYXgXkTsAS0oqdKjo=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=kfm9fNc7bGqRLA/2gSux2n+ddxvpW/qyBK2QZeIzk79EM1qhzrkx/VnsXk+VELHQ4 L1Yyqj6Tnsga/SY1Cl6hVcUPG6ASOgFmRz1y4J5jPvrK6isvMqPMSpakbkt0WVIZXc vQYdrV2PIZk2m/UUUVOjZ9uTbh65yVeEp+FahcNQ= Received: from DFLE115.ent.ti.com (dfle115.ent.ti.com [10.64.6.36]) by lelv0266.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 457DUsUt110033 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 7 Jun 2024 08:30:54 -0500 Received: from DFLE103.ent.ti.com (10.64.6.24) by DFLE115.ent.ti.com (10.64.6.36) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.23; Fri, 7 Jun 2024 08:30:53 -0500 Received: from lelvsmtp6.itg.ti.com (10.180.75.249) by DFLE103.ent.ti.com (10.64.6.24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.23 via Frontend Transport; Fri, 7 Jun 2024 08:30:53 -0500 Received: from localhost (ti.dhcp.ti.com [172.24.227.95] (may be forged)) by lelvsmtp6.itg.ti.com (8.15.2/8.15.2) with ESMTP id 457DUr5d116566; Fri, 7 Jun 2024 08:30:53 -0500 From: Devarsh Thakkar To: , , , , , , , , , , CC: , , , , , , , , , , , , Subject: [PATCH v13 08/13] math.h: Use kernel-doc syntax for divison macros Date: Fri, 7 Jun 2024 19:00:52 +0530 Message-ID: <20240607133052.3555642-1-devarsht@ti.com> X-Mailer: git-send-email 2.39.1 In-Reply-To: <20240607131900.3535250-1-devarsht@ti.com> References: <20240607131900.3535250-1-devarsht@ti.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Enable rEST documentation for divison macros DIV_ROUND_CLOSEST and DIV_ROUND_CLOSEST_ULL by using kernel-doc markup and syntax for documenting them. Signed-off-by: Devarsh Thakkar --- V1->V13 : No change (Patch introduced in V12) include/linux/math.h | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/include/linux/math.h b/include/linux/math.h index 79e3dfda77fc..2ab9489bba81 100644 --- a/include/linux/math.h +++ b/include/linux/math.h @@ -140,9 +140,14 @@ */ #define roundclosest(x, y) rounddown((x) + (y) / 2, (y)) -/* - * Divide positive or negative dividend by positive or negative divisor - * and round to closest integer. Result is undefined for negative +/** + * DIV_ROUND_CLOSEST - Divide positive or negative dividend by positive or + * negative divisor and round to closest value + * @x: dividend value + * @divisor: divisor value + * + * Divide positive or negative dividend value @x by positive or negative + * @divisor value and round to closest integer. Result is undefined for negative * divisors if the dividend variable type is unsigned and for negative * dividends if the divisor variable type is unsigned. */ @@ -157,9 +162,15 @@ (((__x) - ((__d) / 2)) / (__d)); \ } \ ) -/* - * Same as above but for u64 dividends. divisor must be a 32-bit - * number. + +/** + * DIV_ROUND_CLOSEST_ULL - Divide 64-bit unsigned dividend by 32-bit divisor and + * round to closest value + * @x: unsigned 64-bit dividend + * @divisor: 32-bit divisor + * + * Divide unsigned 64-bit dividend value @x by 32-bit @divisor value + * and round to closest integer. Result is undefined for negative divisors. */ #define DIV_ROUND_CLOSEST_ULL(x, divisor)( \ { \ From patchwork Fri Jun 7 13:31:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Devarsh Thakkar X-Patchwork-Id: 802497 Received: from fllv0016.ext.ti.com (fllv0016.ext.ti.com [198.47.19.142]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 97DA0194120; Fri, 7 Jun 2024 13:31:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.47.19.142 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717767102; cv=none; b=cbLJZ06Bxx0VZel9Esg+y11xFnWoB8Kcsu3Fk5oVp0bAs53wn8051kbWGwzY+EIaOIWwt6eL1rUtOVWmTMqLFk2nK0bfMYmItDc4iAv5NoNrVCCTFfmFc+Ptcc36JhnAvLjnVVD6GMump+DPjEB+YPmyd5BB444fVrjQ++NrpsA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717767102; c=relaxed/simple; bh=XqLBnbXePtGLuJK13oyHDSQ/geHy7iZ320cBA8k3IQU=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=UAMNnhPJhg2s7NHg4Q7WgvEXtt++51A57nCsnzz1EMZms8wrYN6AB2Bcnm2J214LJbuzVNbycVLbgPiqv1/6xfHYRA54USm2af3amT4FyoNK5OvxLjSoXwkeINnLxZuodU7hTGtGV1q0DWYaQN9YZ/XxkNxr2TYn5zF5BNo52wc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com; spf=pass smtp.mailfrom=ti.com; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b=SzGCP+JP; arc=none smtp.client-ip=198.47.19.142 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ti.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="SzGCP+JP" Received: from lelv0266.itg.ti.com ([10.180.67.225]) by fllv0016.ext.ti.com (8.15.2/8.15.2) with ESMTP id 457DVM8I117429; Fri, 7 Jun 2024 08:31:22 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1717767082; bh=Rv8Hb874Nu8V7306/erfIx0SE7TmvbbVdALGp3wOf+0=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=SzGCP+JPDSTFI+Hj+GjNiwbRof+soYCwKliXrsQiSpUkBnrgqoAXukYfX2JTXZ6FG iV6XGk2v78Gi3KIRZaJ2B7P/gX8WWzOHSE9apjdtzOdrLJzJZzoMsXhhVyMYuR/0w8 O+9MlTLddRwXrsyNP4dY702rCSe+oGYtd57G8Cdk= Received: from DLEE109.ent.ti.com (dlee109.ent.ti.com [157.170.170.41]) by lelv0266.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 457DVM0J110365 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 7 Jun 2024 08:31:22 -0500 Received: from DLEE113.ent.ti.com (157.170.170.24) by DLEE109.ent.ti.com (157.170.170.41) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.23; Fri, 7 Jun 2024 08:31:21 -0500 Received: from lelvsmtp5.itg.ti.com (10.180.75.250) by DLEE113.ent.ti.com (157.170.170.24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.23 via Frontend Transport; Fri, 7 Jun 2024 08:31:21 -0500 Received: from localhost (ti.dhcp.ti.com [172.24.227.95] (may be forged)) by lelvsmtp5.itg.ti.com (8.15.2/8.15.2) with ESMTP id 457DVKdt045230; Fri, 7 Jun 2024 08:31:21 -0500 From: Devarsh Thakkar To: , , , , , , , , , , , , , , , , , , CC: , , , , , , , , , , , , , , Subject: [PATCH v13 09/13] Documentation: core-api: Add math.h macros and functions Date: Fri, 7 Jun 2024 19:01:20 +0530 Message-ID: <20240607133120.3556488-1-devarsht@ti.com> X-Mailer: git-send-email 2.39.1 In-Reply-To: <20240607131900.3535250-1-devarsht@ti.com> References: <20240607131900.3535250-1-devarsht@ti.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Add documentation for rounding, scaling, absolute value and 32-bit division related macros and functions exported by math.h header file. Signed-off-by: Devarsh Thakkar Reviewed-by: Andy Shevchenko Reviewed-by: Randy Dunlap Tested-by: Randy Dunlap --- V13: No change V12: Add Reviewed-by V11: Fix title for math function header V10: Patch introduced V1->V9 (No change) Documentation/core-api/kernel-api.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/core-api/kernel-api.rst b/Documentation/core-api/kernel-api.rst index ae92a2571388..7de494e76fa6 100644 --- a/Documentation/core-api/kernel-api.rst +++ b/Documentation/core-api/kernel-api.rst @@ -185,6 +185,12 @@ Division Functions .. kernel-doc:: lib/math/gcd.c :export: +Rounding, absolute value, division and 32-bit scaling functions +--------------------------------------------------------------- + +.. kernel-doc:: include/linux/math.h + :internal: + UUID/GUID --------- From patchwork Fri Jun 7 13:31:54 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Devarsh Thakkar X-Patchwork-Id: 802753 Received: from fllv0015.ext.ti.com (fllv0015.ext.ti.com [198.47.19.141]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B15C11922F9; Fri, 7 Jun 2024 13:32:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.47.19.141 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717767136; cv=none; b=rG8Ve3YU59EFT8nrT2lZG8mRud31gBBvccI69fvd/Av4nIvBOLpizZ3UsFvR/1u4GQyjQCcoxjHQQ6znr4BV+zaonSXQ2aM4nbwxnrs9uMfBcW7X9TgrzfprVcm37barL3HIFYvTWlDyNeWjzg31cqeNFhgy9kN0xDgd+y7HyN4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717767136; c=relaxed/simple; bh=kZfuzSEeUPfml6Rd0TlPhqKUZn8L+9LoJ89ruY82e28=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=asHfy/8JbokUFafG34WM8KkVhckFCMf/tJYDA2hcSGZpaGtwL935tV/DuTxu7gdPE9RNpFwMs6vc6a54H9xLH+V/mj+TBM4C4lvJOLPyk44rU6mTiiLo6NM0ratvhTLvwCPrvigxJPGZ7LOjfRhGAlYYaZKFSXaEsLkXK1S81jg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com; spf=pass smtp.mailfrom=ti.com; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b=rQQtiCuC; arc=none smtp.client-ip=198.47.19.141 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ti.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="rQQtiCuC" Received: from fllv0035.itg.ti.com ([10.64.41.0]) by fllv0015.ext.ti.com (8.15.2/8.15.2) with ESMTP id 457DVu2G090886; Fri, 7 Jun 2024 08:31:56 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1717767116; bh=eN1N+QhRfZ6M7DFDtmniJJZ3o/3i4PVj8Gpafzs1Zno=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=rQQtiCuCKkCVZZU+Ea4/RIEXv+WCnLbsBLQCww1lSIF9a1ro4OyZdbxlM+1Uxn5dR ESQITxnEgF527tUXuQ16BschxQv8LMBin9BtlgAI9OPWysvcR4AH3f18nC0M3S1r8Z xO5jOGvyVv4XLi+a0YsA6v7H94Y6p5w6R+awkr0Y= Received: from DFLE103.ent.ti.com (dfle103.ent.ti.com [10.64.6.24]) by fllv0035.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 457DVu5t070865 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 7 Jun 2024 08:31:56 -0500 Received: from DFLE108.ent.ti.com (10.64.6.29) by DFLE103.ent.ti.com (10.64.6.24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.23; Fri, 7 Jun 2024 08:31:55 -0500 Received: from lelvsmtp5.itg.ti.com (10.180.75.250) by DFLE108.ent.ti.com (10.64.6.29) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.23 via Frontend Transport; Fri, 7 Jun 2024 08:31:56 -0500 Received: from localhost (ti.dhcp.ti.com [172.24.227.95] (may be forged)) by lelvsmtp5.itg.ti.com (8.15.2/8.15.2) with ESMTP id 457DVtqt045820; Fri, 7 Jun 2024 08:31:55 -0500 From: Devarsh Thakkar To: , , , , , , , , , , , , , , CC: , , , , , , , , , , , , , , Subject: [PATCH v13 10/13] lib: add basic KUnit test for lib/math Date: Fri, 7 Jun 2024 19:01:54 +0530 Message-ID: <20240607133154.3557512-1-devarsht@ti.com> X-Mailer: git-send-email 2.39.1 In-Reply-To: <20240607131900.3535250-1-devarsht@ti.com> References: <20240607131900.3535250-1-devarsht@ti.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 From: Daniel Latypov Add basic test coverage for files that don't require any config options: * part of math.h (what seem to be the most commonly used macros) * gcd.c * lcm.c * int_sqrt.c * reciprocal_div.c (Ignored int_pow.c since it's a simple textbook algorithm.) These tests aren't particularly interesting, but they * provide short and simple examples of parameterized tests * provide a place to add tests for any new files in this dir * are written so adding new test cases to cover edge cases should be easy * looking at code coverage, we hit all the branches in the .c files Signed-off-by: Daniel Latypov Reviewed-by: David Gow Reviewed-by: Andy Shevchenko [devarsht: Rebase to 6.9, remove kernel.h, update Kconfig and change license to GPL] Signed-off-by: Devarsh Thakkar --- Changes since v11: * Add Reviewed-by tag Changes since v10: * Include headers per IWYU principle and add module description Changes since v9: * Added Kconfig dependency for KUNIT Changes since v8: * Remove unrequired header file linux/kernel.h Changes since v7: * Rebase to linux-next, change license to GPL as suggested by checkpatch. Changes since v6: * No change Changes since v5: * add in test cases for roundup/rounddown * address misc comments from David Changes since v4: * add in test cases for some math.h macros (abs, round_up/round_down, div_round_down/closest) * use parameterized testing less to keep things terser Changes since v3: * fix `checkpatch.pl --strict` warnings * add test cases for gcd(0,0) and lcm(0,0) * minor: don't test both gcd(a,b) and gcd(b,a) when a == b Changes since v2: mv math_test.c => math_kunit.c Changes since v1: * Rebase and rewrite to use the new parameterized testing support. * misc: fix overflow in literal and inline int_sqrt format string. * related: commit 1f0e943df68a ("Documentation: kunit: provide guidance for testing many inputs") was merged explaining the patterns shown here. * there's an in-flight patch to update it for parameterized testing. --- lib/math/Kconfig | 14 ++ lib/math/Makefile | 1 + lib/math/math_kunit.c | 294 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 309 insertions(+) create mode 100644 lib/math/math_kunit.c diff --git a/lib/math/Kconfig b/lib/math/Kconfig index 0634b428d0cb..f738d8a433ea 100644 --- a/lib/math/Kconfig +++ b/lib/math/Kconfig @@ -15,3 +15,17 @@ config PRIME_NUMBERS config RATIONAL tristate + +config MATH_KUNIT_TEST + tristate "KUnit test for math helper functions" + depends on KUNIT + default KUNIT_ALL_TESTS + + help + This builds unit test for math helper functions as defined in lib/math + and math.h. + + For more information on KUNIT and unit tests in general, please refer + to the KUnit documentation in Documentation/dev-tools/kunit/. + + If unsure, say N. diff --git a/lib/math/Makefile b/lib/math/Makefile index 91fcdb0c9efe..dcf65d10dab2 100644 --- a/lib/math/Makefile +++ b/lib/math/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_RATIONAL) += rational.o obj-$(CONFIG_TEST_DIV64) += test_div64.o obj-$(CONFIG_RATIONAL_KUNIT_TEST) += rational-test.o +obj-$(CONFIG_MATH_KUNIT_TEST) += math_kunit.o diff --git a/lib/math/math_kunit.c b/lib/math/math_kunit.c new file mode 100644 index 000000000000..be27f2afb8e4 --- /dev/null +++ b/lib/math/math_kunit.c @@ -0,0 +1,294 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Simple KUnit suite for math helper funcs that are always enabled. + * + * Copyright (C) 2020, Google LLC. + * Author: Daniel Latypov + */ + +#include +#include +#include +#include +#include +#include +#include + +static void abs_test(struct kunit *test) +{ + KUNIT_EXPECT_EQ(test, abs((char)0), (char)0); + KUNIT_EXPECT_EQ(test, abs((char)42), (char)42); + KUNIT_EXPECT_EQ(test, abs((char)-42), (char)42); + + /* The expression in the macro is actually promoted to an int. */ + KUNIT_EXPECT_EQ(test, abs((short)0), 0); + KUNIT_EXPECT_EQ(test, abs((short)42), 42); + KUNIT_EXPECT_EQ(test, abs((short)-42), 42); + + KUNIT_EXPECT_EQ(test, abs(0), 0); + KUNIT_EXPECT_EQ(test, abs(42), 42); + KUNIT_EXPECT_EQ(test, abs(-42), 42); + + KUNIT_EXPECT_EQ(test, abs(0L), 0L); + KUNIT_EXPECT_EQ(test, abs(42L), 42L); + KUNIT_EXPECT_EQ(test, abs(-42L), 42L); + + KUNIT_EXPECT_EQ(test, abs(0LL), 0LL); + KUNIT_EXPECT_EQ(test, abs(42LL), 42LL); + KUNIT_EXPECT_EQ(test, abs(-42LL), 42LL); + + /* Unsigned types get casted to signed. */ + KUNIT_EXPECT_EQ(test, abs(0ULL), 0LL); + KUNIT_EXPECT_EQ(test, abs(42ULL), 42LL); +} + +static void int_sqrt_test(struct kunit *test) +{ + KUNIT_EXPECT_EQ(test, int_sqrt(0UL), 0UL); + KUNIT_EXPECT_EQ(test, int_sqrt(1UL), 1UL); + KUNIT_EXPECT_EQ(test, int_sqrt(4UL), 2UL); + KUNIT_EXPECT_EQ(test, int_sqrt(5UL), 2UL); + KUNIT_EXPECT_EQ(test, int_sqrt(8UL), 2UL); + KUNIT_EXPECT_EQ(test, int_sqrt(1UL << 30), 1UL << 15); +} + +static void round_up_test(struct kunit *test) +{ + KUNIT_EXPECT_EQ(test, round_up(0, 1), 0); + KUNIT_EXPECT_EQ(test, round_up(1, 2), 2); + KUNIT_EXPECT_EQ(test, round_up(3, 2), 4); + KUNIT_EXPECT_EQ(test, round_up((1 << 30) - 1, 2), 1 << 30); + KUNIT_EXPECT_EQ(test, round_up((1 << 30) - 1, 1 << 29), 1 << 30); +} + +static void round_down_test(struct kunit *test) +{ + KUNIT_EXPECT_EQ(test, round_down(0, 1), 0); + KUNIT_EXPECT_EQ(test, round_down(1, 2), 0); + KUNIT_EXPECT_EQ(test, round_down(3, 2), 2); + KUNIT_EXPECT_EQ(test, round_down((1 << 30) - 1, 2), (1 << 30) - 2); + KUNIT_EXPECT_EQ(test, round_down((1 << 30) - 1, 1 << 29), 1 << 29); +} + +/* These versions can round to numbers that aren't a power of two */ +static void roundup_test(struct kunit *test) +{ + KUNIT_EXPECT_EQ(test, roundup(0, 1), 0); + KUNIT_EXPECT_EQ(test, roundup(1, 2), 2); + KUNIT_EXPECT_EQ(test, roundup(3, 2), 4); + KUNIT_EXPECT_EQ(test, roundup((1 << 30) - 1, 2), 1 << 30); + KUNIT_EXPECT_EQ(test, roundup((1 << 30) - 1, 1 << 29), 1 << 30); + + KUNIT_EXPECT_EQ(test, roundup(3, 2), 4); + KUNIT_EXPECT_EQ(test, roundup(4, 3), 6); +} + +static void rounddown_test(struct kunit *test) +{ + KUNIT_EXPECT_EQ(test, rounddown(0, 1), 0); + KUNIT_EXPECT_EQ(test, rounddown(1, 2), 0); + KUNIT_EXPECT_EQ(test, rounddown(3, 2), 2); + KUNIT_EXPECT_EQ(test, rounddown((1 << 30) - 1, 2), (1 << 30) - 2); + KUNIT_EXPECT_EQ(test, rounddown((1 << 30) - 1, 1 << 29), 1 << 29); + + KUNIT_EXPECT_EQ(test, rounddown(3, 2), 2); + KUNIT_EXPECT_EQ(test, rounddown(4, 3), 3); +} + +static void div_round_up_test(struct kunit *test) +{ + KUNIT_EXPECT_EQ(test, DIV_ROUND_UP(0, 1), 0); + KUNIT_EXPECT_EQ(test, DIV_ROUND_UP(20, 10), 2); + KUNIT_EXPECT_EQ(test, DIV_ROUND_UP(21, 10), 3); + KUNIT_EXPECT_EQ(test, DIV_ROUND_UP(21, 20), 2); + KUNIT_EXPECT_EQ(test, DIV_ROUND_UP(21, 99), 1); +} + +static void div_round_closest_test(struct kunit *test) +{ + KUNIT_EXPECT_EQ(test, DIV_ROUND_CLOSEST(0, 1), 0); + KUNIT_EXPECT_EQ(test, DIV_ROUND_CLOSEST(20, 10), 2); + KUNIT_EXPECT_EQ(test, DIV_ROUND_CLOSEST(21, 10), 2); + KUNIT_EXPECT_EQ(test, DIV_ROUND_CLOSEST(25, 10), 3); +} + +/* Generic test case for unsigned long inputs. */ +struct test_case { + unsigned long a, b; + unsigned long result; +}; + +static struct test_case gcd_cases[] = { + { + .a = 0, .b = 0, + .result = 0, + }, + { + .a = 0, .b = 1, + .result = 1, + }, + { + .a = 2, .b = 2, + .result = 2, + }, + { + .a = 2, .b = 4, + .result = 2, + }, + { + .a = 3, .b = 5, + .result = 1, + }, + { + .a = 3 * 9, .b = 3 * 5, + .result = 3, + }, + { + .a = 3 * 5 * 7, .b = 3 * 5 * 11, + .result = 15, + }, + { + .a = 1 << 21, + .b = (1 << 21) - 1, + .result = 1, + }, +}; + +KUNIT_ARRAY_PARAM(gcd, gcd_cases, NULL); + +static void gcd_test(struct kunit *test) +{ + const char *message_fmt = "gcd(%lu, %lu)"; + const struct test_case *test_param = test->param_value; + + KUNIT_EXPECT_EQ_MSG(test, test_param->result, + gcd(test_param->a, test_param->b), + message_fmt, test_param->a, + test_param->b); + + if (test_param->a == test_param->b) + return; + + /* gcd(a,b) == gcd(b,a) */ + KUNIT_EXPECT_EQ_MSG(test, test_param->result, + gcd(test_param->b, test_param->a), + message_fmt, test_param->b, + test_param->a); +} + +static struct test_case lcm_cases[] = { + { + .a = 0, .b = 0, + .result = 0, + }, + { + .a = 0, .b = 1, + .result = 0, + }, + { + .a = 1, .b = 2, + .result = 2, + }, + { + .a = 2, .b = 2, + .result = 2, + }, + { + .a = 3 * 5, .b = 3 * 7, + .result = 3 * 5 * 7, + }, +}; + +KUNIT_ARRAY_PARAM(lcm, lcm_cases, NULL); + +static void lcm_test(struct kunit *test) +{ + const char *message_fmt = "lcm(%lu, %lu)"; + const struct test_case *test_param = test->param_value; + + KUNIT_EXPECT_EQ_MSG(test, test_param->result, + lcm(test_param->a, test_param->b), + message_fmt, test_param->a, + test_param->b); + + if (test_param->a == test_param->b) + return; + + /* lcm(a,b) == lcm(b,a) */ + KUNIT_EXPECT_EQ_MSG(test, test_param->result, + lcm(test_param->b, test_param->a), + message_fmt, test_param->b, + test_param->a); +} + +struct u32_test_case { + u32 a, b; + u32 result; +}; + +static struct u32_test_case reciprocal_div_cases[] = { + { + .a = 0, .b = 1, + .result = 0, + }, + { + .a = 42, .b = 20, + .result = 2, + }, + { + .a = 42, .b = 9999, + .result = 0, + }, + { + .a = (1 << 16), .b = (1 << 14), + .result = 1 << 2, + }, +}; + +KUNIT_ARRAY_PARAM(reciprocal_div, reciprocal_div_cases, NULL); + +static void reciprocal_div_test(struct kunit *test) +{ + const struct u32_test_case *test_param = test->param_value; + struct reciprocal_value rv = reciprocal_value(test_param->b); + + KUNIT_EXPECT_EQ_MSG(test, test_param->result, + reciprocal_divide(test_param->a, rv), + "reciprocal_divide(%u, %u)", + test_param->a, test_param->b); +} + +static void reciprocal_scale_test(struct kunit *test) +{ + KUNIT_EXPECT_EQ(test, reciprocal_scale(0u, 100), 0u); + KUNIT_EXPECT_EQ(test, reciprocal_scale(1u, 100), 0u); + KUNIT_EXPECT_EQ(test, reciprocal_scale(1u << 4, 1 << 28), 1u); + KUNIT_EXPECT_EQ(test, reciprocal_scale(1u << 16, 1 << 28), 1u << 12); + KUNIT_EXPECT_EQ(test, reciprocal_scale(~0u, 1 << 28), (1u << 28) - 1); +} + +static struct kunit_case math_test_cases[] = { + KUNIT_CASE(abs_test), + KUNIT_CASE(int_sqrt_test), + KUNIT_CASE(round_up_test), + KUNIT_CASE(round_down_test), + KUNIT_CASE(roundup_test), + KUNIT_CASE(rounddown_test), + KUNIT_CASE(div_round_up_test), + KUNIT_CASE(div_round_closest_test), + KUNIT_CASE_PARAM(gcd_test, gcd_gen_params), + KUNIT_CASE_PARAM(lcm_test, lcm_gen_params), + KUNIT_CASE_PARAM(reciprocal_div_test, reciprocal_div_gen_params), + KUNIT_CASE(reciprocal_scale_test), + {} +}; + +static struct kunit_suite math_test_suite = { + .name = "lib-math", + .test_cases = math_test_cases, +}; + +kunit_test_suites(&math_test_suite); + +MODULE_DESCRIPTION("Math helper functions kunit test"); +MODULE_LICENSE("GPL"); From patchwork Fri Jun 7 13:32:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Devarsh Thakkar X-Patchwork-Id: 802496 Received: from lelv0143.ext.ti.com (lelv0143.ext.ti.com [198.47.23.248]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 97E241922F9; Fri, 7 Jun 2024 13:32:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.47.23.248 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717767158; cv=none; b=MOdAr4il4jlcKqf8DrnIQNCzd7h5+8z2ZblZvZLv1AVkbbC2YDv9AOL3g/9SwgAjMvv8lCvq0xCFSedfKwy88DyjMwb2vEMcU4k2aMgbw3pcRkHKW3tIsn67isbnGfPQeqcuQ0u1K25naAajfmYmuHNWB0vFEfTzE8ai4q8xkw8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717767158; c=relaxed/simple; bh=OB9nuMUaz2RJ7fDsZfmD6NlU0tEuo2P3GDvpOX39uHs=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Fh9mZEHtJrh5hJ/aeZy8oDTewI7C2JeMywzjtsmSLjxGdZaB4l1Fl71rq3zm5ClVgDNHgKD6b1b4QdBCR0Xus/xHbDoWkFR/fvXZJwjkW+bLEu5Gw65DJQvtThnju3IeXiUiZ88mNnGtyfLeLVMzA03RC+Tp1GlsRsNOoR1/nic= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com; spf=pass smtp.mailfrom=ti.com; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b=mdu1SN37; arc=none smtp.client-ip=198.47.23.248 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ti.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="mdu1SN37" Received: from fllv0034.itg.ti.com ([10.64.40.246]) by lelv0143.ext.ti.com (8.15.2/8.15.2) with ESMTP id 457DWKYH086877; Fri, 7 Jun 2024 08:32:20 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1717767140; bh=cxjK4DYOMf+01WJ2Qh8aciagA8IuXgOO5npXQIszqls=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=mdu1SN37oY8CfEk05w2niFM7d5+o3Hn11jSxwb9H44ylAIKMBoLCzB4RTHjVKyXxF qCMIK5RuWkgWvZFY13d41lf48NzXPBUXyo3xyP82CZ13G415F9+wrdphcH3X9Fo6uy FVYjm0VKlrOFhugL0gnyxe7QfZpRo/SHyHEpxSIU= Received: from DLEE115.ent.ti.com (dlee115.ent.ti.com [157.170.170.26]) by fllv0034.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 457DWKt4099910 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 7 Jun 2024 08:32:20 -0500 Received: from DLEE105.ent.ti.com (157.170.170.35) by DLEE115.ent.ti.com (157.170.170.26) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.23; Fri, 7 Jun 2024 08:32:20 -0500 Received: from lelvsmtp5.itg.ti.com (10.180.75.250) by DLEE105.ent.ti.com (157.170.170.35) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.23 via Frontend Transport; Fri, 7 Jun 2024 08:32:20 -0500 Received: from localhost (ti.dhcp.ti.com [172.24.227.95] (may be forged)) by lelvsmtp5.itg.ti.com (8.15.2/8.15.2) with ESMTP id 457DWJ85046487; Fri, 7 Jun 2024 08:32:20 -0500 From: Devarsh Thakkar To: , , , , , , , , , , , , , , , CC: , , , , , , , , , , , , , Subject: [PATCH v13 11/13] lib: math_kunit: Add tests for new macros related to rounding to nearest value Date: Fri, 7 Jun 2024 19:02:19 +0530 Message-ID: <20240607133219.3558319-1-devarsht@ti.com> X-Mailer: git-send-email 2.39.1 In-Reply-To: <20240607131900.3535250-1-devarsht@ti.com> References: <20240607131900.3535250-1-devarsht@ti.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Add tests for round_closest_up/down and roundclosest macros which round to nearest multiple of specified argument. These are tested with kunit tool as shared here [1] : Link: https://gist.github.com/devarsht/3f9042825be3da4e133b8f4eda067876 [1] Signed-off-by: Devarsh Thakkar Acked-by: Andy Shevchenko --- V1->V13 (No change, patch introduced in V8) lib/math/math_kunit.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/lib/math/math_kunit.c b/lib/math/math_kunit.c index be27f2afb8e4..05022f010be6 100644 --- a/lib/math/math_kunit.c +++ b/lib/math/math_kunit.c @@ -70,6 +70,26 @@ static void round_down_test(struct kunit *test) KUNIT_EXPECT_EQ(test, round_down((1 << 30) - 1, 1 << 29), 1 << 29); } +static void round_closest_up_test(struct kunit *test) +{ + KUNIT_EXPECT_EQ(test, round_closest_up(17, 4), 16); + KUNIT_EXPECT_EQ(test, round_closest_up(15, 4), 16); + KUNIT_EXPECT_EQ(test, round_closest_up(14, 4), 16); + KUNIT_EXPECT_EQ(test, round_closest_up((1 << 30) - 1, 1 << 30), 1 << 30); + KUNIT_EXPECT_EQ(test, round_closest_up((1 << 30) + 1, 1 << 30), 1 << 30); + KUNIT_EXPECT_EQ(test, round_closest_up((1 << 30) - 1, 2), 1 << 30); +} + +static void round_closest_down_test(struct kunit *test) +{ + KUNIT_EXPECT_EQ(test, round_closest_down(17, 4), 16); + KUNIT_EXPECT_EQ(test, round_closest_down(15, 4), 16); + KUNIT_EXPECT_EQ(test, round_closest_down(14, 4), 12); + KUNIT_EXPECT_EQ(test, round_closest_down((1 << 30) - 1, 1 << 30), 1 << 30); + KUNIT_EXPECT_EQ(test, round_closest_down((1 << 30) + 1, 1 << 30), 1 << 30); + KUNIT_EXPECT_EQ(test, round_closest_down((1 << 30) - 1, 2), (1 << 30) - 2); +} + /* These versions can round to numbers that aren't a power of two */ static void roundup_test(struct kunit *test) { @@ -95,6 +115,18 @@ static void rounddown_test(struct kunit *test) KUNIT_EXPECT_EQ(test, rounddown(4, 3), 3); } +static void roundclosest_test(struct kunit *test) +{ + KUNIT_EXPECT_EQ(test, roundclosest(21, 5), 20); + KUNIT_EXPECT_EQ(test, roundclosest(19, 5), 20); + KUNIT_EXPECT_EQ(test, roundclosest(17, 5), 15); + KUNIT_EXPECT_EQ(test, roundclosest((1 << 30), 3), (1 << 30) - 1); + KUNIT_EXPECT_EQ(test, roundclosest((1 << 30) - 1, 1 << 29), 1 << 30); + + KUNIT_EXPECT_EQ(test, roundclosest(4, 3), 3); + KUNIT_EXPECT_EQ(test, roundclosest(5, 3), 6); +} + static void div_round_up_test(struct kunit *test) { KUNIT_EXPECT_EQ(test, DIV_ROUND_UP(0, 1), 0); @@ -272,8 +304,11 @@ static struct kunit_case math_test_cases[] = { KUNIT_CASE(int_sqrt_test), KUNIT_CASE(round_up_test), KUNIT_CASE(round_down_test), + KUNIT_CASE(round_closest_up_test), + KUNIT_CASE(round_closest_down_test), KUNIT_CASE(roundup_test), KUNIT_CASE(rounddown_test), + KUNIT_CASE(roundclosest_test), KUNIT_CASE(div_round_up_test), KUNIT_CASE(div_round_closest_test), KUNIT_CASE_PARAM(gcd_test, gcd_gen_params), From patchwork Fri Jun 7 13:32:53 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Devarsh Thakkar X-Patchwork-Id: 802752 Received: from fllv0016.ext.ti.com (fllv0016.ext.ti.com [198.47.19.142]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 99415195978; Fri, 7 Jun 2024 13:33:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.47.19.142 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717767200; cv=none; b=dUayqq+4ZJATYRdq/426uM7GBaZoV1f4sRhRqJuk1GH9Grnmr4xcZk7hOdL7qKF7wlXVSoPo1NHlnFgCoeBSh/7TGnEDc3EvOz6MGwvRqAuiX4aF5CLmePaXASy0T4Iu1fHcVqa+5VJPHen+G4aZOIwY81KRCii/aaOaLCbVXDY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717767200; c=relaxed/simple; bh=sTv+4L8NPPBBpg+i+qz9cePrzDf4eKNTqM5Xda6LRw0=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=O4KZQM1uqWYHSsgzYzsQJH8lNlqj7Gz0da5XV6VewDb0F0V08LEwz86FFZApmIn+RKgKIsLt7Il6WV4wAVwJiMmAXL2W8iFhlAy+WdvXJbnWaY8j+oeAE9XBH9K7n9y816B7GcxN64TGkuLOQsE+e8sm++Q6PfAGXIm3vZ/BhR8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com; spf=pass smtp.mailfrom=ti.com; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b=L6NYNlPj; arc=none smtp.client-ip=198.47.19.142 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ti.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="L6NYNlPj" Received: from lelv0265.itg.ti.com ([10.180.67.224]) by fllv0016.ext.ti.com (8.15.2/8.15.2) with ESMTP id 457DWsoO118337; Fri, 7 Jun 2024 08:32:54 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1717767174; bh=dnlV6EZfbKSSOB5yAkozQxyQBhab8cR780BU+/JTZrQ=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=L6NYNlPjRde1WkOLXLqkzPfOtF1fM01Iox5Db8LaU+PXPUP3EhmR0AJQgTT855PCg tTnKhY/zUIsqKBlWxrMXKA0TcDA8n1gwyMUoMGkd9zp2JBDjtBN/s3lVqfCEuBFLmg VlSqGMjGto1chRA//GNAmNzTk49pP8+u5raJiBZs= Received: from DLEE115.ent.ti.com (dlee115.ent.ti.com [157.170.170.26]) by lelv0265.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 457DWsWD017223 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 7 Jun 2024 08:32:54 -0500 Received: from DLEE103.ent.ti.com (157.170.170.33) by DLEE115.ent.ti.com (157.170.170.26) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.23; Fri, 7 Jun 2024 08:32:54 -0500 Received: from lelvsmtp6.itg.ti.com (10.180.75.249) by DLEE103.ent.ti.com (157.170.170.33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.23 via Frontend Transport; Fri, 7 Jun 2024 08:32:54 -0500 Received: from localhost (ti.dhcp.ti.com [172.24.227.95] (may be forged)) by lelvsmtp6.itg.ti.com (8.15.2/8.15.2) with ESMTP id 457DWrnp119514; Fri, 7 Jun 2024 08:32:54 -0500 From: Devarsh Thakkar To: , , , , , , CC: , , , , , , , , , , , , , , , , , , , , Subject: [PATCH v13 12/13] media: imagination: Round to closest multiple for cropping region Date: Fri, 7 Jun 2024 19:02:53 +0530 Message-ID: <20240607133253.3559339-1-devarsht@ti.com> X-Mailer: git-send-email 2.39.1 In-Reply-To: <20240607131900.3535250-1-devarsht@ti.com> References: <20240607131900.3535250-1-devarsht@ti.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 If neither of the flags to round down (V4L2_SEL_FLAG_LE) or round up (V4L2_SEL_FLAG_GE) are specified by the user, then round to nearest multiple of requested value while updating the crop rectangle coordinates. Use the rounding macro which gives preference to rounding down in case two nearest values (high and low) are possible to raise the probability of cropping rectangle falling inside the bound region. This complies with the VIDIOC_G_SELECTION, VIDIOC_S_SELECTION ioctl description as documented in v4l uapi [1] which specifies that driver should choose crop rectangle as close as possible if no flags are passed by user-space, as quoted below : "``0`` - The driver can adjust the rectangle size freely and shall choose a crop/compose rectangle as close as possible to the requested one." Link: https://www.kernel.org/doc/Documentation/userspace-api/media/v4l/vidioc-g-selection.rst [1] Signed-off-by: Devarsh Thakkar --- V9->V13: No change V8: Update commit message with specification reference V1->V7 (No change, patch introduced in V7) --- drivers/media/platform/imagination/e5010-jpeg-enc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/imagination/e5010-jpeg-enc.c b/drivers/media/platform/imagination/e5010-jpeg-enc.c index 4b6fbe99d5ff..ea96b1bc5315 100644 --- a/drivers/media/platform/imagination/e5010-jpeg-enc.c +++ b/drivers/media/platform/imagination/e5010-jpeg-enc.c @@ -517,10 +517,10 @@ static int e5010_s_selection(struct file *file, void *fh, struct v4l2_selection switch (s->flags) { case 0: - s->r.width = round_down(s->r.width, queue->fmt->frmsize.step_width); - s->r.height = round_down(s->r.height, queue->fmt->frmsize.step_height); - s->r.left = round_down(s->r.left, queue->fmt->frmsize.step_width); - s->r.top = round_down(s->r.top, 2); + s->r.width = round_closest_down(s->r.width, queue->fmt->frmsize.step_width); + s->r.height = round_closest_down(s->r.height, queue->fmt->frmsize.step_height); + s->r.left = round_closest_down(s->r.left, queue->fmt->frmsize.step_width); + s->r.top = round_closest_down(s->r.top, 2); if (s->r.left + s->r.width > queue->width) s->r.width = round_down(s->r.width + s->r.left - queue->width, From patchwork Fri Jun 7 13:33:43 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Devarsh Thakkar X-Patchwork-Id: 802495 Received: from lelv0142.ext.ti.com (lelv0142.ext.ti.com [198.47.23.249]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 23C84194128; Fri, 7 Jun 2024 13:33:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.47.23.249 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717767241; cv=none; b=N5rL567WYA2jjc18TNu8Iezn+No7vpvVJUF3iP/TW6AWGhYmeJXgboWz8BOPjlEUd0oPYpD7mmcnPqPk4ApTDxlnGKI8EhCt4phYx26HuxT1DMPG8u4ON7Ce8ys4Uxz5eysHyMG/mI/iG5kiejFKm4+SOfgxn+u7ZW3pEloZmdo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717767241; c=relaxed/simple; bh=0YLhmyjheVzSXXSOrOiwBn47uAon+CPY+/qhGgmycN8=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=u5xpL4jolin2QhIbz3RG1Eg50AamYrkME33OWEGrEGtLOh6giILLy79RQYqDX1lUHQKE5czh+IkuNrnh6zandAno94asD+qeaquUnan++5rtDF1Yeyreng4waWJVM16BcqPPvQb8TZfPDX+UrB2Wi/5cFquRFYDU2/joeRPL9AE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com; spf=pass smtp.mailfrom=ti.com; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b=vP0kU3Jq; arc=none smtp.client-ip=198.47.23.249 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ti.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="vP0kU3Jq" Received: from lelv0265.itg.ti.com ([10.180.67.224]) by lelv0142.ext.ti.com (8.15.2/8.15.2) with ESMTP id 457DXi1C004677; Fri, 7 Jun 2024 08:33:44 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1717767224; bh=2ALN0fauWepwefecugaG1Bmw8RPodxWqs7BmCdEY/wc=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=vP0kU3JqKWvQIDVxw14ev+g6s2u+Uxnc8QtMVxuiGmEHboH+IlRWtURfW9ibS3Vrq QEdm/YTGIYftPw+BI2Mv6/bOdCfc+rtsT5+ztOuHWOdfcGQ9t428NGZ1W5wMHPIC1z Q0DttF7O/tE0D5xZ3JQvnIRpYRpb+TQpzhvu6Zl4= Received: from DFLE115.ent.ti.com (dfle115.ent.ti.com [10.64.6.36]) by lelv0265.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 457DXi0u017642 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 7 Jun 2024 08:33:44 -0500 Received: from DFLE105.ent.ti.com (10.64.6.26) by DFLE115.ent.ti.com (10.64.6.36) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.23; Fri, 7 Jun 2024 08:33:44 -0500 Received: from lelvsmtp6.itg.ti.com (10.180.75.249) by DFLE105.ent.ti.com (10.64.6.26) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.23 via Frontend Transport; Fri, 7 Jun 2024 08:33:44 -0500 Received: from localhost (ti.dhcp.ti.com [172.24.227.95] (may be forged)) by lelvsmtp6.itg.ti.com (8.15.2/8.15.2) with ESMTP id 457DXhoI120585; Fri, 7 Jun 2024 08:33:44 -0500 From: Devarsh Thakkar To: , , , , , , , , , CC: , , , , , , , , , , , , , , , , , Subject: [PATCH v13 13/13] gpu: ipu-v3: Use generic macro for rounding closest to specified value Date: Fri, 7 Jun 2024 19:03:43 +0530 Message-ID: <20240607133343.3560760-1-devarsht@ti.com> X-Mailer: git-send-email 2.39.1 In-Reply-To: <20240607131900.3535250-1-devarsht@ti.com> References: <20240607131900.3535250-1-devarsht@ti.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Use generic macro round_closest_up() for rounding closest to specified value instead of using local macro round_closest(). There is no change from functionality point of view as round_closest_up() is functionally same as the previously used local macro round_closest(). Signed-off-by: Devarsh Thakkar --- V9-V13: No change V8: Update commit message V1->V7 : (No change, patch introduced in V7) drivers/gpu/ipu-v3/ipu-image-convert.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/ipu-v3/ipu-image-convert.c b/drivers/gpu/ipu-v3/ipu-image-convert.c index 841316582ea9..5192a8b5c02c 100644 --- a/drivers/gpu/ipu-v3/ipu-image-convert.c +++ b/drivers/gpu/ipu-v3/ipu-image-convert.c @@ -477,8 +477,6 @@ static int calc_image_resize_coefficients(struct ipu_image_convert_ctx *ctx, return 0; } -#define round_closest(x, y) round_down((x) + (y)/2, (y)) - /* * Find the best aligned seam position for the given column / row index. * Rotation and image offsets are out of scope. @@ -565,7 +563,7 @@ static void find_best_seam(struct ipu_image_convert_ctx *ctx, * The closest input sample position that we could actually * start the input tile at, 19.13 fixed point. */ - in_pos_aligned = round_closest(in_pos, 8192U * in_align); + in_pos_aligned = round_closest_up(in_pos, 8192U * in_align); /* Convert 19.13 fixed point to integer */ in_pos_rounded = in_pos_aligned / 8192U;