Skip to content

Instantly share code, notes, and snippets.

@devarsht
Created February 5, 2024 10:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save devarsht/22a744d999080de6e813bcfb5a596272 to your computer and use it in GitHub Desktop.
Save devarsht/22a744d999080de6e813bcfb5a596272 to your computer and use it in GitHub Desktop.
e5010_git_range_diff_v4_to_v4
1: 13e6e07d2f95 ! 1: 9b5df301ad35 dt-bindings: media: Add bindings for Imagination E5010 JPEG Encoder driver
@@ Metadata
Author: Devarsh Thakkar <devarsht@ti.com>
## Commit message ##
- dt-bindings: media: Add bindings for Imagination E5010 JPEG Encoder driver
+ media: dt-bindings: Add Imagination E5010 JPEG Encoder
- Add dt-bindings for Imagination E5010 JPEG Encoder driver which is
- implemented as stateful V4L2 M2M driver.
+ 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.
+
+ [1]: AM62A TRM (Section 7.6 is for JPEG Encoder)
+ Link: https://www.ti.com/lit/pdf/spruj16
Co-developed-by: David Huang <d-huang@ti.com>
Signed-off-by: David Huang <d-huang@ti.com>
Signed-off-by: Devarsh Thakkar <devarsht@ti.com>
+ ---
+ V2: No change
+ V3:
+ - Add vendor specific compatible
+ - Update reg names
+ - Update clocks to 1
+ - Fix dts example with proper naming
+ V4:
+ - Use ti-specific compatible ti,am62a-jpeg-enc as secondary one
+ - Update commit message and title
+ - Remove clock-names as only single clock
+
+ Link to previous commit:
+ https://lore.kernel.org/all/20230816152210.4080779-2-devarsht@ti.com/
## Documentation/devicetree/bindings/media/img,e5010-jpeg-enc.yaml (new) ##
@@
@@ Documentation/devicetree/bindings/media/img,e5010-jpeg-enc.yaml (new)
+ compatible:
+ oneOf:
+ - items:
-+ - const: ti,e5010-jpeg-enc
++ - const: ti,am62a-jpeg-enc
+ - const: img,e5010-jpeg-enc
+ - const: img,e5010-jpeg-enc
+
@@ Documentation/devicetree/bindings/media/img,e5010-jpeg-enc.yaml (new)
+ clocks:
+ maxItems: 1
+
-+ clock-names:
-+ items:
-+ - const: core_clk
-+
+ interrupts:
+ maxItems: 1
+
@@ Documentation/devicetree/bindings/media/img,e5010-jpeg-enc.yaml (new)
+ - reg-names
+ - interrupts
+ - clocks
-+ - clock-names
+
+additionalProperties: false
+
@@ Documentation/devicetree/bindings/media/img,e5010-jpeg-enc.yaml (new)
+ <0x00 0xfd20200 0x00 0x200>;
+ reg-names = "core", "mmu";
+ clocks = <&k3_clks 201 0>;
-+ clock-names = "core_clk";
+ power-domains = <&k3_pds 201 TI_SCI_PD_EXCLUSIVE>;
+ interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+ };
-: ------------ > 2: 17be475ddbb0 media: jpeg: Add reference quantization and huffman tables
2: 5f35f30d7cd7 ! 3: 4e08cfba9341 media: imagination: Add E5010 JPEG Encoder driver
@@ Commit message
All v4l2-compliance tests are passing [2] :
v4l2-compliance -s -f -a -d /dev/video0 -e /dev/video1
- Total for e5010 device /dev/video0: 70, Succeeded: 70, Failed: 0,
+ Total for e5010 device /dev/video0: 78, Succeeded: 78, Failed: 0,
Warnings: 0
+
NOTE: video1 here is VIVID test pattern generator
Also tests [3] were run manually to verify below driver features:
@@ Commit message
TODO:
Add MMU and memory tiling support
- [1]: AM62A TRM (Section 7.6 is for JPEG Encoder)
+ [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/17348fc509fe375a630a798196edbb73
+ Link: https://gist.github.com/devarsht/867b1d646bca3f3877edb1f3638aae31
[3]: E5010 JPEG Encoder Manual tests :
-
Performance:
- Link: https://gist.github.com/devarsht/ef5aba211aae45166681b8b4418d4e65
+ Link: https://gist.github.com/devarsht/63d835093195181866ae9a85de880d3c
Functionality:
- Link: https://gist.github.com/devarsht/bfef1e3ead8e858b09cbf418aea753e8
+ Link: https://gist.github.com/devarsht/253e485e86661a3051e711f97ec3c5ac
Compression Quality:
- Link: https://gist.github.com/devarsht/345df9bf7157b4ca094293760e257451
+ Link: https://gist.github.com/devarsht/e16d8b73c8107ac78cc77ad79fd6299f
Multi Instance:
- Link: https://gist.github.com/devarsht/4b4d734eeb9e0e616837c0836ddbc769
+ Link: https://gist.github.com/devarsht/58af9ccf822963d2bf8f0c2f4481438a
+
+ Link: https://gist.github.com/devarsht/ea31179199393c2026ae457219bb6321
Co-developed-by: David Huang <d-huang@ti.com>
Signed-off-by: David Huang <d-huang@ti.com>
Signed-off-by: Devarsh Thakkar <devarsht@ti.com>
+ ---
+ V2:
+ No change
+
+ 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
+
+ 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
+
+ Link to previous commit:
+ https://lore.kernel.org/all/20230816152210.4080779-3-devarsht@ti.com/
## MAINTAINERS ##
@@ MAINTAINERS: F: drivers/auxdisplay/img-ascii-lcd.c
@@ drivers/media/platform/imagination/e5010-jpeg-enc-hw.c (new)
+
+int e5010_hw_enable_output_address_error_irq(void __iomem *core_base, u32 enable)
+{
-+ int ret;
-+
-+ ret = write_reg_field_not_busy(core_base, core_base,
++ 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);
-+ return ret;
+}
+
+bool e5010_hw_pic_done_irq(void __iomem *core_base)
+{
+ u32 reg;
-+ bool pic_done;
+
+ reg = readl(core_base + JASPER_INTERRUPT_STATUS_OFFSET);
-+ pic_done = (reg & JASPER_INTERRUPT_STATUS_CR_PICTURE_DONE_IRQ_MASK) ? true : false;
-+
-+ return pic_done;
++ return reg & JASPER_INTERRUPT_STATUS_CR_PICTURE_DONE_IRQ_MASK;
+}
+
+bool e5010_hw_output_address_irq(void __iomem *core_base)
+{
+ u32 reg;
-+ bool output_address_error;
+
+ reg = readl(core_base + JASPER_INTERRUPT_STATUS_OFFSET);
-+ output_address_error = (reg & JASPER_INTERRUPT_STATUS_CR_OUTPUT_ADDRESS_ERROR_IRQ_MASK) ?
-+ true : false;
-+
-+ return output_address_error;
++ return reg & JASPER_INTERRUPT_STATUS_CR_OUTPUT_ADDRESS_ERROR_IRQ_MASK;
+}
+
+int e5010_hw_enable_picture_done_irq(void __iomem *core_base, u32 enable)
+{
-+ int ret;
-+
-+ ret = write_reg_field_not_busy(core_base, core_base,
++ 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);
-+ return ret;
+}
+
+int e5010_hw_enable_auto_clock_gating(void __iomem *core_base, u32 enable)
+{
-+ int ret;
-+
-+ ret = write_reg_field_not_busy(core_base, core_base,
++ 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);
-+ return ret;
+}
+
+int e5010_hw_enable_manual_clock_gating(void __iomem *core_base, u32 enable)
+{
-+ int ret;
-+
-+ ret = write_reg_field_not_busy(core_base, core_base,
++ 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);
-+ return ret;
+}
+
+int e5010_hw_enable_crc_check(void __iomem *core_base, u32 enable)
+{
-+ int ret;
-+
-+ ret = write_reg_field_not_busy(core_base, core_base,
++ 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);
-+ return ret;
+}
+
+int e5010_hw_set_input_source_to_memory(void __iomem *core_base, u32 set)
+{
-+ int ret;
-+
-+ ret = write_reg_field_not_busy(core_base, core_base,
++ 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);
-+ return ret;
+}
+
+int e5010_hw_set_input_luma_addr(void __iomem *core_base, u32 val)
+{
-+ int ret;
-+
-+ ret = write_reg_field_not_busy(core_base, core_base,
++ return write_reg_field_not_busy(core_base, core_base,
+ INPUT_LUMA_BASE_OFFSET,
+ INPUT_LUMA_BASE_CR_INPUT_LUMA_BASE_MASK, 0, val);
-+ return ret;
+}
+
+int e5010_hw_set_input_chroma_addr(void __iomem *core_base, u32 val)
+{
-+ int ret;
-+
-+ ret = write_reg_field_not_busy(core_base, core_base,
++ return write_reg_field_not_busy(core_base, core_base,
+ INPUT_CHROMA_BASE_OFFSET,
+ INPUT_CHROMA_BASE_CR_INPUT_CHROMA_BASE_MASK, 0, val);
-+ return ret;
+}
+
+int e5010_hw_set_output_base_addr(void __iomem *core_base, u32 val)
+{
-+ int ret;
-+
-+ ret = write_reg_field_not_busy(core_base, core_base,
++ 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);
-+ return ret;
+}
+
+int e5010_hw_set_horizontal_size(void __iomem *core_base, u32 val)
+{
-+ int ret;
-+
-+ ret = write_reg_field_not_busy(core_base, core_base,
++ 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);
-+ return ret;
+}
+
+int e5010_hw_set_vertical_size(void __iomem *core_base, u32 val)
+{
-+ int ret;
-+
-+ ret = write_reg_field_not_busy(core_base, core_base,
++ 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);
-+ return ret;
+}
+
+int e5010_hw_set_luma_stride(void __iomem *core_base, u32 bytesperline)
+{
-+ int ret;
+ u32 val = bytesperline / 64;
+
-+ ret = write_reg_field_not_busy(core_base, core_base,
++ 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);
-+ return ret;
+}
+
+int e5010_hw_set_chroma_stride(void __iomem *core_base, u32 bytesperline)
+{
-+ int ret;
+ u32 val = bytesperline / 64;
+
-+ ret = write_reg_field_not_busy(core_base, core_base,
++ 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);
-+ return ret;
+}
+
+int e5010_hw_set_input_subsampling(void __iomem *core_base, u32 val)
+{
-+ int ret;
-+
-+ ret = write_reg_field_not_busy(core_base, core_base,
++ 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);
-+ return ret;
+}
+
+int e5010_hw_set_chroma_order(void __iomem *core_base, u32 val)
+{
-+ int ret;
-+
-+ ret = write_reg_field_not_busy(core_base, core_base,
++ 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);
-+ return ret;
+}
+
+void e5010_hw_set_output_max_size(void __iomem *core_base, u32 val)
@@ drivers/media/platform/imagination/e5010-jpeg-enc-hw.c (new)
+
+int e5010_hw_set_qpvalue(void __iomem *core_base, u32 offset, u32 val)
+{
-+ int ret;
-+
-+ ret = write_reg_field_not_busy(core_base, core_base, offset, 0xffffffff, 0, val);
-+ return ret;
++ 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)
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+#include <media/v4l2-event.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-mem2mem.h>
++#include <media/jpeg-enc-reftables.h>
+#include <media/videobuf2-v4l2.h>
+#include <media/videobuf2-dma-contig.h>
++#include <media/jpeg.h>
+#include "e5010-jpeg-enc.h"
+#include "e5010-jpeg-enc-hw.h"
+
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+ },
+};
+
-+/* Luma and chroma qp table to acheive 50% compression quality
-+ * This is as per example in Annex K.1 of IS0/IEC 10918-1:1994(E)
-+ */
-+static const u8 luma[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[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 IS0/IEC 10918-1:1994(E)
-+ */
-+static const u8 marker_luma_dc[] = {
-+ 0x00, 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 IS0/IEC 10918-1:1994(E)
-+ */
-+static const u8 marker_luma_ac[] = {
-+ 0x10, 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 IS0/IEC 10918-1:1994(E)
-+ */
-+static const u8 marker_chroma_dc[] = {
-+ 0x01, 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 IS0/IEC 10918-1:1994(E)
-+ */
-+static const u8 marker_chroma_ac[] = {
-+ 0x11, 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
-+};
-+
+static unsigned int debug;
+module_param(debug, uint, 0644);
+MODULE_PARM_DESC(debug, "debug level");
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+
+static struct e5010_q_data *get_queue(struct e5010_context *ctx, enum v4l2_buf_type type)
+{
-+ switch (type) {
-+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
-+ return &ctx->out_queue;
-+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
-+ return &ctx->cap_queue;
-+ default:
-+ return ERR_PTR(-EINVAL);
-+ }
-+
-+ return ERR_PTR(-EINVAL);
++ return (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ? &ctx->out_queue : &ctx->cap_queue;
+}
+
+static void calculate_qp_tables(struct e5010_context *ctx)
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+ contrast *= INCREASE;
+ }
+
-+ for (i = 0; i < 64; i++) {
-+ long long delta = chroma[i] * contrast + luminosity;
-+ int val = (int)(chroma[i] + delta);
++ 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[i] * contrast + luminosity;
-+ val = (int)(luma[i] + delta);
++ 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;
+ }
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+{
+ strscpy(cap->driver, E5010_MODULE_NAME, sizeof(cap->driver));
+ strscpy(cap->card, E5010_MODULE_NAME, sizeof(cap->card));
-+ snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", E5010_MODULE_NAME);
-+ cap->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
-+ cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+
+ return 0;
+}
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+ struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
+ struct v4l2_plane_pix_format *plane_fmt = pix_mp->plane_fmt;
+
-+ if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) {
-+ v4l2_err(&ctx->e5010->v4l2_dev, "G_FMT with Invalid type: %d\n", f->type);
-+ return -EINVAL;
-+ }
-+
+ queue = get_queue(ctx, f->type);
-+ if (IS_ERR(queue))
-+ return PTR_ERR(queue);
+
+ pix_mp->flags = 0;
+ pix_mp->field = V4L2_FIELD_NONE;
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+static int e5010_jpeg_try_fmt(struct v4l2_format *f, struct e5010_context *ctx)
+{
+ struct e5010_fmt *fmt;
-+ 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;
+
-+ if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) {
-+ v4l2_err(&ctx->e5010->v4l2_dev, "G_FMT with Invalid type: %d\n", f->type);
-+ return -EINVAL;
-+ }
-+
+ fmt = find_format(f);
+ if (!fmt) {
+ if (V4L2_TYPE_IS_OUTPUT(f->type))
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+ return -EINVAL;
+ }
+
-+ queue = get_queue(ctx, f->type);
-+ if (IS_ERR(queue))
-+ return PTR_ERR(queue);
-+
-+ queue->fmt = fmt;
-+ queue->width = pix_mp->width;
-+ queue->height = pix_mp->height;
-+
+ if (V4L2_TYPE_IS_OUTPUT(f->type)) {
+ if (!pix_mp->colorspace)
+ pix_mp->colorspace = V4L2_COLORSPACE_JPEG;
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+ 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;
-+ }
+ } 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;
-+ memset(plane_fmt[0].reserved, 0, sizeof(plane_fmt[0].reserved));
+ 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;
-+ plane_fmt[0].sizeimage = queue->sizeimage[0];
++ 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;
-+ pix_mp->pixelformat = fmt->fourcc;
-+ queue->width_adjusted = pix_mp->width;
-+ queue->height_adjusted = pix_mp->height;
-+ pix_mp->num_planes = fmt->num_planes;
-+ memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved));
+
+ 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), queue->width_adjusted, queue->height_adjusted,
-+ queue->sizeimage[0], queue->sizeimage[1],
-+ (queue->fmt->fourcc & 0xff),
-+ (queue->fmt->fourcc >> 8) & 0xff,
-+ (queue->fmt->fourcc >> 16) & 0xff,
-+ (queue->fmt->fourcc >> 24) & 0xff);
++ 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;
+}
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+{
+ 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)
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+ return -EBUSY;
+ }
+
-+ return e5010_jpeg_try_fmt(f, ctx);
++ 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;
++ }
++ } 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)
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+ return -EINVAL;
+
+ queue = get_queue(ctx, s->type);
-+ if (IS_ERR(queue))
-+ return PTR_ERR(queue);
+
+ switch (s->target) {
+ case V4L2_SEL_TGT_CROP_DEFAULT:
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+ return -EINVAL;
+
+ queue = get_queue(ctx, s->type);
-+ if (IS_ERR(queue))
-+ return PTR_ERR(queue);
+
+ queue->crop.left = 0;
+ queue->crop.top = 0;
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+ /* src_vq */
+ memset(src_vq, 0, sizeof(*src_vq));
+ src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
-+ src_vq->dma_attrs = DMA_ATTR_FORCE_CONTIGUOUS;
+ src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+ src_vq->drv_priv = ctx;
+ src_vq->buf_struct_size = sizeof(struct e5010_buffer);
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+ /* dst_vq */
+ memset(dst_vq, 0, sizeof(*dst_vq));
+ dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-+ src_vq->dma_attrs = DMA_ATTR_FORCE_CONTIGUOUS;
+ dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+ dst_vq->drv_priv = ctx;
+ dst_vq->buf_struct_size = sizeof(struct e5010_buffer);
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+ calculate_qp_tables(ctx);
+ break;
+ default:
-+ v4l2_err(&ctx->e5010->v4l2_dev, "Invalid control, id = %d, val = %d\n",
-+ ctrl->id, ctrl->val);
+ return -EINVAL;
+ }
+
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+ 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);
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+ 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);
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+ return 0;
+}
+
-+static struct video_device e5010_videodev = {
-+ .name = E5010_MODULE_NAME,
-+ .fops = &e5010_fops,
-+ .ioctl_ops = &e5010_ioctl_ops,
-+ .minor = -1,
-+ .release = video_device_release_empty,
-+ .vfl_dir = VFL_DIR_M2M,
-+ .device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING,
-+};
-+
+static void header_write(struct e5010_context *ctx, u8 *addr, unsigned int *offset,
+ unsigned int no_bytes, unsigned long bits)
+{
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+ /* Huffman tables */
+ header_write(ctx, buffer, offset, 2, DHT_MARKER);
+ header_write(ctx, buffer, offset, 2, LH_DC);
-+ for (i = 0 ; i < (LH_DC - 2); i++)
-+ header_write(ctx, buffer, offset, 1, marker_luma_dc[i]);
++ 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);
-+ for (i = 0 ; i < (LH_AC - 2); i++)
-+ header_write(ctx, buffer, offset, 1, marker_luma_ac[i]);
++ 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);
-+ for (i = 0 ; i < (LH_DC - 2); i++)
-+ header_write(ctx, buffer, offset, 1, marker_chroma_dc[i]);
++ 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);
-+ for (i = 0 ; i < (LH_AC - 2); i++)
-+ header_write(ctx, buffer, offset, 1, marker_chroma_ac[i]);
++ 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)
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+ mutex_init(&e5010->mutex);
+ spin_lock_init(&e5010->hw_lock);
+
-+ e5010->vdev = &e5010_videodev;
++ e5010->vdev = video_device_alloc();
++ if (!e5010->vdev) {
++ dev_err(e5010->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;
-+ e5010->vdev->queue = NULL;
-+ e5010->vdev->prio = NULL;
-+ e5010->vdev->dev_parent = NULL;
-+ e5010->vdev->minor = -1;
+
+ ret = v4l2_device_register(&pdev->dev, &e5010->v4l2_dev);
+ if (ret)
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+
+ video_set_drvdata(e5010->vdev, e5010);
+
-+ ret = video_register_device(e5010->vdev, VFL_TYPE_VIDEO, 0);
-+ if (ret) {
-+ dev_err_probe(e5010->dev, ret, "failed to register video device\n");
-+ goto fail_after_v4l2_register;
-+ }
-+
-+ v4l2_info(&e5010->v4l2_dev, "Device registered as /dev/video%d\n",
-+ e5010->vdev->num);
-+
+ 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(e5010->dev, ret, "Missing 'core' resources area\n");
-+ goto fail_after_video_register_device;
++ 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(e5010->dev, ret, "Missing 'mmu' resources area\n");
-+ goto fail_after_video_register_device;
++ goto fail_after_v4l2_register;
+ }
+
+ e5010->last_context_run = NULL;
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+ E5010_MODULE_NAME, e5010);
+ if (ret) {
+ dev_err_probe(e5010->dev, ret, "failed to register IRQ %d\n", irq);
-+ goto fail_after_video_register_device;
++ goto fail_after_v4l2_register;
+ }
+
-+ e5010->clk = devm_clk_get(&pdev->dev, "core_clk");
++ e5010->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(e5010->clk)) {
+ ret = PTR_ERR(e5010->clk);
+ dev_err_probe(e5010->dev, ret, "failed to get clock\n");
-+ goto fail_after_video_register_device;
++ goto fail_after_v4l2_register;
+ }
+
+ pm_runtime_enable(e5010->dev);
+
++ ret = video_register_device(e5010->vdev, VFL_TYPE_VIDEO, 0);
++ if (ret) {
++ dev_err_probe(e5010->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:
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+ 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[])
+{
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+ struct e5010_q_data *queue;
+ int i;
+
-+ if (!V4L2_TYPE_IS_MULTIPLANAR(vq->type)) {
-+ v4l2_err(&ctx->e5010->v4l2_dev, "queue setup with Invalid type: %d\n", vq->type);
-+ return -EINVAL;
-+ }
-+
+ queue = get_queue(ctx, vq->type);
-+ if (IS_ERR(queue))
-+ return PTR_ERR(queue);
+
+ if (*nplanes) {
+ if (*nplanes != queue->fmt->num_planes)
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+ return 0;
+ }
+
-+ *nbuffers = max_t(unsigned int, *nbuffers, 1);
+ *nplanes = queue->fmt->num_planes;
+ for (i = 0; i < *nplanes; i++)
+ sizes[i] = queue->sizeimage[i];
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+ vbuf->field = V4L2_FIELD_NONE;
+
+ queue = get_queue(ctx, vb->vb2_queue->type);
-+ if (IS_ERR(queue))
-+ return PTR_ERR(queue);
+
+ for (i = 0; i < queue->fmt->num_planes; i++) {
+ if (vb2_plane_size(vb, i) < (unsigned long)queue->sizeimage[i]) {
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+ v4l2_m2m_dst_buf_is_last(ctx->fh.m2m_ctx)) {
+ struct e5010_q_data *queue = get_queue(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+
-+ if (IS_ERR(queue))
-+ return;
-+
+ vbuf->sequence = queue->sequence++;
+ v4l2_m2m_last_buffer_done(ctx->fh.m2m_ctx, vbuf);
+ v4l2_event_queue_fh(&ctx->fh, &e5010_eos_event);
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+
+ struct e5010_q_data *queue = get_queue(ctx, q->type);
+
-+ if (IS_ERR(queue))
-+ return PTR_ERR(queue);
+ queue->streaming = true;
+ v4l2_m2m_update_start_streaming_state(ctx->fh.m2m_ctx, q);
+ queue->sequence = 0;
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+ ret = pm_runtime_resume_and_get(ctx->e5010->dev);
+ if (ret < 0) {
+ v4l2_err(&ctx->e5010->v4l2_dev, "failed to power up jpeg\n");
-+ return ret;
++ goto fail;
+ }
+
+ ret = e5010_init_device(ctx->e5010);
-+ if (ret)
++ 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;
+}
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+static void e5010_stop_streaming(struct vb2_queue *q)
+{
+ struct e5010_context *ctx = vb2_get_drv_priv(q);
-+ struct vb2_v4l2_buffer *vbuf;
+ struct e5010_q_data *queue;
+
+ queue = get_queue(ctx, q->type);
-+ if (IS_ERR(queue))
-+ return;
+
+ queue->streaming = false;
+
-+ if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-+ 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, VB2_BUF_STATE_ERROR);
-+ }
-+ } 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, VB2_BUF_STATE_ERROR);
-+ }
-+ }
++ 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);
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new)
+ 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 size\n");
++ v4l2_err(&e5010->v4l2_dev, "failed to set output base address\n");
+ goto device_busy_err;
+ }
+
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment