Re: [PATCH] [media] staging: allow omap4iss to be modular
Hi Tony, On Thursday 12 June 2014 22:30:44 Tony Lindgren wrote: * Laurent Pinchart laurent.pinch...@ideasonboard.com [140612 08:32]: On Thursday 12 June 2014 08:15:35 Tony Lindgren wrote: * Laurent Pinchart laurent.pinch...@ideasonboard.com [140612 07:52]: On Wednesday 11 June 2014 07:47:54 Tony Lindgren wrote: These should just use either pinctrl-single.c instead for muxing. Or if they are not mux registers, we do have the syscon mapping available in omap4.dtsi that pbias-regulator.c is already using. Laurent, got any better ideas? The ISS driver needs to write a single register, which contains several independent fields. They thus need to be controlled by a single driver. Some of them might be considered to be related to pinmuxing (although I disagree on that), others are certainly not about muxing (there are clock gate bits for instance). Using the syscon mapping seems like the best option. I'll give it a try. OK if it's not strictly pinctrl related then let's not use pinctrl-single,bits for it. You may be able to implement one or more framework drivers for it for pinctrl/regulator/clock/transceiver whatever that register is doing. In any case it's best to have that handling in a separate helper driver somewhere as it's a separate piece of hardware from the camera module. If it does not fit into any existing frameworks then it's best to have it in a separate driver with the camera driver. The register contains the following fields that control the two CSI2 PHYs (PHY1 and PHY2). 31CAMERARX_CSI22_LANEENABLE2 PHY2 Lane 2 (CSI22_DX2, CSI22_DY2) Enable 30CAMERARX_CSI22_LANEENABLE1 PHY2 Lane 1 (CSI22_DX1, CSI22_DY1) Enable 29CAMERARX_CSI22_LANEENABLE0 PHY2 Lane 0 (CSI22_DX0, CSI22_DY0) Enable 28CAMERARX_CSI21_LANEENABLE4 PHY1 Lane 4 (CSI21_DX4, CSI21_DY4) Enable 27CAMERARX_CSI21_LANEENABLE3 PHY1 Lane 3 (CSI21_DX3, CSI21_DY3) Enable 26CAMERARX_CSI21_LANEENABLE2 PHY1 Lane 2 (CSI21_DX2, CSI21_DY2) Enable 25CAMERARX_CSI21_LANEENABLE1 PHY1 Lane 1 (CSI21_DX1, CSI21_DY1) Enable 24CAMERARX_CSI21_LANEENABLE0 PHY1 Lane 0 (CSI21_DX0, CSI21_DY0) Enable 21CAMERARX_CSI22_CTRLCLKEN PHY2 Clock Enable 20:19 CAMERARX_CSI22_CAMMODE PHY2 Mode (CCP2, CSI1, CSI2) 18CAMERARX_CSI21_CTRLCLKEN PHY1 Clock Enable 17:16 CAMERARX_CSI21_CAMMODE PHY1 Mode (CCP2, CSI1, CSI2) Bits 18 and 21 could be exposed through CCF. Bits 24 to 31 enable/disable the CSI2 lanes, so it could be argued that they could be exposed through the pinctrl framework. However, they need to be configured independently, possibly at runtime. I'm thus not sure pinctrl would be a good idea. Bits 17:16 and 20:19 don't fit in existing frameworks. OK thanks for the info. Sounds like drivers/phy might be the right location for it then and then the phy driver can use the syscon regmap. Given that this register is specific to the ISS, I think handling it as a separate device through a separate driver would only complicate the implementation without any real benefit. Even though it's one register, it shoud still be treated separately from the camera driver. The problems with keeping the register access to the control module in the camera driver are at least following: 1. They live in separate hardware modules that can be clocked separately Actually I don't think that's true. The CSI2 PHY is part of the camera device, with all its registers but the one above in the camera device register space. For some weird reason a couple of bits were pushed to the control module, but that doesn't make the CSI2 PHY itself a separate device. 2. Doing a read-back to flush a posted write in one hardware module most likely won't flush the write to other and that can lead into hard to find mysterious bugs The OMAP4 ISS driver can just read back the CAMERA_RX register, can't it ? 3. If we ever have a common system control module driver, we need to rewrite all the system control module register tinkering in the drivers Sure, but that's already the case today, as the OMAP4 ISS driver already accesses the control module register directly. I won't make that worse :-) So it's best to try to use an existing framework for it. That avoids tons of pain later on ;) I agree, but I don't think the PHY framework would be the right abstraction. As explained above the CSI2 PHY is part of the OMAP4 ISS, so modeling its single control module register as a PHY would be a hack. -- Regards, Laurent Pinchart -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] [media] staging: allow omap4iss to be modular
* Laurent Pinchart laurent.pinch...@ideasonboard.com [140612 23:48]: On Thursday 12 June 2014 22:30:44 Tony Lindgren wrote: 1. They live in separate hardware modules that can be clocked separately Actually I don't think that's true. The CSI2 PHY is part of the camera device, with all its registers but the one above in the camera device register space. For some weird reason a couple of bits were pushed to the control module, but that doesn't make the CSI2 PHY itself a separate device. Yes they are separate. Anything in the system control module is a separate hardware module from the other devices. So in this case the CSI2 PHY is part of the system control module, not the camera module. 2. Doing a read-back to flush a posted write in one hardware module most likely won't flush the write to other and that can lead into hard to find mysterious bugs The OMAP4 ISS driver can just read back the CAMERA_RX register, can't it ? Right, but you would have to do readbacks both from the phy register and camera register to ensure writes get written. It's best to keep the logic completely separate especially considering that they can be clocked separately. 3. If we ever have a common system control module driver, we need to rewrite all the system control module register tinkering in the drivers Sure, but that's already the case today, as the OMAP4 ISS driver already accesses the control module register directly. I won't make that worse :-) Well it's in staging for a reason :) So it's best to try to use an existing framework for it. That avoids tons of pain later on ;) I agree, but I don't think the PHY framework would be the right abstraction. As explained above the CSI2 PHY is part of the OMAP4 ISS, so modeling its single control module register as a PHY would be a hack. Well that register belongs to the system control module, not the camera module. It's not like the camera IO space is out of registers or something! :) We're already handling similar control module phy cases, see for example drivers/phy/phy-omap-control.c. Maybe you have most of the code already there? Regards, Tony -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: AF9033 / IT913X: Avermedia A835B(1835) only works sporadically
On Fri, Jun 13, 2014 at 12:27:54AM +0300, Antti Palosaari wrote: Moikka, The reason is that Avermedia has programmed wrong tuner ID to device eeprom. For one IT9135BX device I have it is set 0x38 (whilst Windows driver programs 0x60), no idea how others. That same issues was for AF9015 too, where I added USB ID based overrides for certain Avermedia models. I think I will do same for AF9035 driver. Hello Antti, Thank you for the patch. Problem solved. I checked with both versions 3.42.3.3 and 3.39.1.0 of dvb-usb-it9135-02.fw. With 3.39.1.0 I usually get some blocks when zapping (they disappear after a short while when staying on the same channel). With 3.42.3.3 I don't have this issue. Looks like 3.42.3.3 is an improvement. Kind regards, Sebastian -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] [media] staging: allow omap4iss to be modular
Hi Tony, On Friday 13 June 2014 00:53:25 Tony Lindgren wrote: * Laurent Pinchart laurent.pinch...@ideasonboard.com [140612 23:48]: On Thursday 12 June 2014 22:30:44 Tony Lindgren wrote: 1. They live in separate hardware modules that can be clocked separately Actually I don't think that's true. The CSI2 PHY is part of the camera device, with all its registers but the one above in the camera device register space. For some weird reason a couple of bits were pushed to the control module, but that doesn't make the CSI2 PHY itself a separate device. Yes they are separate. Anything in the system control module is a separate hardware module from the other devices. So in this case the CSI2 PHY is part of the system control module, not the camera module. Section 8.2.3 (ISS CSI2 PHY) of the OMAP4460 TRM (revision AA) documents the CSI2 PHY is being part of the ISS, with three PHY registers in the ISS register space (not counting the PHY interrupt and status bits in several other ISS registers) and one register in the system control module register space. It's far from clear which power domain(s) is (are) involved. 2. Doing a read-back to flush a posted write in one hardware module most likely won't flush the write to other and that can lead into hard to find mysterious bugs The OMAP4 ISS driver can just read back the CAMERA_RX register, can't it ? Right, but you would have to do readbacks both from the phy register and camera register to ensure writes get written. It's best to keep the logic completely separate especially considering that they can be clocked separately. 3. If we ever have a common system control module driver, we need to rewrite all the system control module register tinkering in the drivers Sure, but that's already the case today, as the OMAP4 ISS driver already accesses the control module register directly. I won't make that worse :-) Well it's in staging for a reason :) So it's best to try to use an existing framework for it. That avoids tons of pain later on ;) I agree, but I don't think the PHY framework would be the right abstraction. As explained above the CSI2 PHY is part of the OMAP4 ISS, so modeling its single control module register as a PHY would be a hack. Well that register belongs to the system control module, not the camera module. It's not like the camera IO space is out of registers or something! :) The PHY has 3 registers in the ISS I/O space and one register in the control module I/O space. I have no idea why they've split it that way. The clock enable bits are especially interested, the source clock (CAM_PHY_CTRL_FCLK) comes from the ISS as documented in section 8.1.1 (ISS Integration), is gated by the control module (the gated clock is called CTRLCLK) and then goes back to the ISS CSI2 PHY (it's mentioned in the CSI2 PHY REGISTER1 documentation). We're already handling similar control module phy cases, see for example drivers/phy/phy-omap-control.c. Maybe you have most of the code already there? I'm afraid not. For PHYs that are in the system control module that solution is perfectly fine, but the CSI2 PHY isn't (or at least not all of it). I would be fine with writing a separate PHY driver if the PHY was completely separate. As the documentation doesn't make it clear which part of the hardware belongs to which module, matching the software implementation with an unknown hardware implementation would be pretty difficult :-) If you have a couple of minutes to spare and can look at the CSI2 PHY documentation in the TRM, you might be more successful than me figuring out how the hardware is implemented. -- Regards, Laurent Pinchart -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] [media] staging: allow omap4iss to be modular
* Laurent Pinchart laurent.pinch...@ideasonboard.com [140613 03:30]: Hi Tony, On Friday 13 June 2014 00:53:25 Tony Lindgren wrote: * Laurent Pinchart laurent.pinch...@ideasonboard.com [140612 23:48]: On Thursday 12 June 2014 22:30:44 Tony Lindgren wrote: 1. They live in separate hardware modules that can be clocked separately Actually I don't think that's true. The CSI2 PHY is part of the camera device, with all its registers but the one above in the camera device register space. For some weird reason a couple of bits were pushed to the control module, but that doesn't make the CSI2 PHY itself a separate device. Yes they are separate. Anything in the system control module is a separate hardware module from the other devices. So in this case the CSI2 PHY is part of the system control module, not the camera module. Section 8.2.3 (ISS CSI2 PHY) of the OMAP4460 TRM (revision AA) documents the CSI2 PHY is being part of the ISS, with three PHY registers in the ISS register space (not counting the PHY interrupt and status bits in several other ISS registers) and one register in the system control module register space. It's far from clear which power domain(s) is (are) involved. OK I see. The register in the system control module just contains some pin and clock related resources for the phy. 2. Doing a read-back to flush a posted write in one hardware module most likely won't flush the write to other and that can lead into hard to find mysterious bugs The OMAP4 ISS driver can just read back the CAMERA_RX register, can't it ? Right, but you would have to do readbacks both from the phy register and camera register to ensure writes get written. It's best to keep the logic completely separate especially considering that they can be clocked separately. 3. If we ever have a common system control module driver, we need to rewrite all the system control module register tinkering in the drivers Sure, but that's already the case today, as the OMAP4 ISS driver already accesses the control module register directly. I won't make that worse :-) Well it's in staging for a reason :) So it's best to try to use an existing framework for it. That avoids tons of pain later on ;) I agree, but I don't think the PHY framework would be the right abstraction. As explained above the CSI2 PHY is part of the OMAP4 ISS, so modeling its single control module register as a PHY would be a hack. Well that register belongs to the system control module, not the camera module. It's not like the camera IO space is out of registers or something! :) The PHY has 3 registers in the ISS I/O space and one register in the control module I/O space. I have no idea why they've split it that way. The clock enable bits are especially interested, the source clock (CAM_PHY_CTRL_FCLK) comes from the ISS as documented in section 8.1.1 (ISS Integration), is gated by the control module (the gated clock is called CTRLCLK) and then goes back to the ISS CSI2 PHY (it's mentioned in the CSI2 PHY REGISTER1 documentation). We're already handling similar control module phy cases, see for example drivers/phy/phy-omap-control.c. Maybe you have most of the code already there? I'm afraid not. For PHYs that are in the system control module that solution is perfectly fine, but the CSI2 PHY isn't (or at least not all of it). I would be fine with writing a separate PHY driver if the PHY was completely separate. As the documentation doesn't make it clear which part of the hardware belongs to which module, matching the software implementation with an unknown hardware implementation would be pretty difficult :-) Yeah it seems the phy driver would still have to use the pin resources in the system control module. If you have a couple of minutes to spare and can look at the CSI2 PHY documentation in the TRM, you might be more successful than me figuring out how the hardware is implemented. Took a look and it seems the phy is split into two parts. So probably using the syscon mapping for the register in scm are is a good start. At least then there's some protection from drivers tinkering directly with the system control modules. Maybe s ee what drivers/regulator/pbias-regulator.c is doing with syscon to see if that works? Moving that to some phy driver later on should be trivial if needed :) Regards, Tony -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] [RFC] [media] omap3isp: try to fix dependencies
commit 2a0a5472af5c (omap3isp: Use the ARM DMA IOMMU-aware operations) brought the omap3isp driver closer to using standard APIs, but also introduced two problems: a) it selects a particular IOMMU driver for no good reason. This just causes hard to track dependency chains, in my case breaking an experimental patch set that tries to reenable !MMU support on ARM multiplatform kernels. Since the driver doesn't have a dependency on the actual IOMMU implementation (other than sitting on the same SoC), this changes the 'select OMAP_IOMMU' to a generic 'depends on IOMMU_API' that reflects the actual usage. b) The driver incorrectly calls into low-level helpers designed to be used by the IOMMU implementation: arm_iommu_{create,attach,release}_mapping. I'm not fixing this here, but adding a FIXME and a dependency on ARM_DMA_USE_IOMMU. I believe the correct solution is to move the calls into the omap iommu driver that currently doesn't have them, and change the isp driver to call generic functions. In addition, this also adds the missing 'select VIDEOBUF2_DMA_CONTIG' that is needed since fbac1400bd1 ([media] omap3isp: Move to videobuf2) Signed-off-by: Arnd Bergmann a...@arndb.de Hi Laurent, Could you have a look at this? It's possible I'm missing something important here, but this is what I currently need to get randconfig builds to use the omap3isp driver. diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 8108c69..15bf61b 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -94,8 +94,9 @@ config VIDEO_M32R_AR_M64278 config VIDEO_OMAP3 tristate OMAP 3 Camera support depends on VIDEO_V4L2 I2C VIDEO_V4L2_SUBDEV_API ARCH_OMAP3 - select ARM_DMA_USE_IOMMU - select OMAP_IOMMU + depends on ARM_DMA_USE_IOMMU # FIXME: use iommu API instead of low-level ARM calls + depends on IOMMU_API + select VIDEOBUF2_DMA_CONTIG ---help--- Driver for an OMAP 3 camera controller. -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] [media] staging: allow omap4iss to be modular
Hi Tony, On Friday 13 June 2014 04:10:12 Tony Lindgren wrote: * Laurent Pinchart laurent.pinch...@ideasonboard.com [140613 03:30]: On Friday 13 June 2014 00:53:25 Tony Lindgren wrote: * Laurent Pinchart laurent.pinch...@ideasonboard.com [140612 23:48]: On Thursday 12 June 2014 22:30:44 Tony Lindgren wrote: 1. They live in separate hardware modules that can be clocked separately Actually I don't think that's true. The CSI2 PHY is part of the camera device, with all its registers but the one above in the camera device register space. For some weird reason a couple of bits were pushed to the control module, but that doesn't make the CSI2 PHY itself a separate device. Yes they are separate. Anything in the system control module is a separate hardware module from the other devices. So in this case the CSI2 PHY is part of the system control module, not the camera module. Section 8.2.3 (ISS CSI2 PHY) of the OMAP4460 TRM (revision AA) documents the CSI2 PHY is being part of the ISS, with three PHY registers in the ISS register space (not counting the PHY interrupt and status bits in several other ISS registers) and one register in the system control module register space. It's far from clear which power domain(s) is (are) involved. OK I see. The register in the system control module just contains some pin and clock related resources for the phy. And the configuration of the PHY mode (CCP2, CSI1 or CSI2). It really seems like random bits :-) 2. Doing a read-back to flush a posted write in one hardware module most likely won't flush the write to other and that can lead into hard to find mysterious bugs The OMAP4 ISS driver can just read back the CAMERA_RX register, can't it ? Right, but you would have to do readbacks both from the phy register and camera register to ensure writes get written. It's best to keep the logic completely separate especially considering that they can be clocked separately. 3. If we ever have a common system control module driver, we need to rewrite all the system control module register tinkering in the drivers Sure, but that's already the case today, as the OMAP4 ISS driver already accesses the control module register directly. I won't make that worse :-) Well it's in staging for a reason :) So it's best to try to use an existing framework for it. That avoids tons of pain later on ;) I agree, but I don't think the PHY framework would be the right abstraction. As explained above the CSI2 PHY is part of the OMAP4 ISS, so modeling its single control module register as a PHY would be a hack. Well that register belongs to the system control module, not the camera module. It's not like the camera IO space is out of registers or something! :) The PHY has 3 registers in the ISS I/O space and one register in the control module I/O space. I have no idea why they've split it that way. The clock enable bits are especially interested, the source clock (CAM_PHY_CTRL_FCLK) comes from the ISS as documented in section 8.1.1 (ISS Integration), is gated by the control module (the gated clock is called CTRLCLK) and then goes back to the ISS CSI2 PHY (it's mentioned in the CSI2 PHY REGISTER1 documentation). We're already handling similar control module phy cases, see for example drivers/phy/phy-omap-control.c. Maybe you have most of the code already there? I'm afraid not. For PHYs that are in the system control module that solution is perfectly fine, but the CSI2 PHY isn't (or at least not all of it). I would be fine with writing a separate PHY driver if the PHY was completely separate. As the documentation doesn't make it clear which part of the hardware belongs to which module, matching the software implementation with an unknown hardware implementation would be pretty difficult :-) Yeah it seems the phy driver would still have to use the pin resources in the system control module. If you have a couple of minutes to spare and can look at the CSI2 PHY documentation in the TRM, you might be more successful than me figuring out how the hardware is implemented. Took a look and it seems the phy is split into two parts. So probably using the syscon mapping for the register in scm are is a good start. At least then there's some protection from drivers tinkering directly with the system control modules. That's my plan. Maybe s ee what drivers/regulator/pbias-regulator.c is doing with syscon to see if that works? Moving that to some phy driver later on should be trivial if needed :) I'll have a look, but I'm not sure whether the same approach will be possible. -- Regards, Laurent Pinchart -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to
Re: [PATCH 00/43] i.MX6 Video capture
Am Donnerstag, den 12.06.2014, 14:05 -0700 schrieb Steve Longerbeam: Ok. Yes, we definitely need preview and MIPI CSI-2, and adding IC to the capture path is nice too, since it allows userland to select arbitrary user resolutions, pixel format color space, and also rotation controls. No question about that. It's just that mostly everyone around here seems to want to capture at least 1080p, or 10-bit grayscale. I hope Freescale drops the 1024-pixel output limitation in their next SoC ... The capture driver decides whether to include the IC in the capture pipeline based on user format and rotation control. I.e. if user colorspace is different from what the sensor can output, IC CSC is required. If user resolution is different from the selected capture cropping rectangle, IC resizer is required, and finally if user requests rotation, the IC rotation unit is required. If none of those are true, the capture driver decides to exclude the IC from the pipeline and send raw sensor frames (well, after cropping anyway) directly to memory via the SMFC. That is too much magic for my taste. Especially since whether or not you can use the IC not only depends on the current video format, but also on whether the other CSI or the MEM_VDIC_MEM path are using the IC at the moment. Since this can change dynamically, it throws a wrench into GStreamer's static capability negotiation, for example. I'd rather have userspace select which CSI should be routed through the IC with media-ctl and then reflect the possible conversions in the respective video_dev's capabilities. So in our driver, the decision to link the IC in a pipeline is made internally by the driver and is not a decision exported to userland. This is exactly the point I am worried about. You lose flexibility and need all sorts of clever conditional code in the driver. It'd be much cleaner to just let userspace control the mux. My plan was to add media device framework support, but only after basic video capture is in place. Our driver is full featured in terms of basic capture support, and it works on all three reference platforms. But I agree it needs to convert subdev's to media entities and allow some of them to be linked via the media controller API. Alright, so we agree that using the media controller API internally is a good idea ... But only some linkages make sense to me. As I explain above, if the IC were to be made a media entity, I think it's linkage should be made internally by the capture driver, and this should not be controllable by userspace. ... but we disagree on whether to export the control to userspace. For more complicated pipelines in front of the CSIs we'll need media-ctl anyway, so using that same API for the internal components, makes sense. It also allows userspace to get a clear and stable picture of the available features for any given multiplexer setting. Heh, we have a mem2mem driver as well, and it also uses IC post-processor task. It uses banding and striping to support resized output frames larger than 1024x1024. It also makes use of IC rotation and CSC. Of course :) But again this is not converted to a media entity. And again, if IC were to be made a standalone media entity, then the mem2mem device would _always_ require the IC post-processor be linked to it, since the essential feature of mem2mem is to make use of IC post-processor task for CSC, resize, and rotation operations. Since the three IC tasks are transparently time-multiplexed, the IC media entity representation could have input and output pads for each of them. The preprocessing (encoding, viewfinder) tasks share an input pad that would be connected to either CSI0, CSI1, or VDI output pad. These links should control the IC mux. The encoding task output pad would represent IDMAC channel 20/CB0 or channel 48/CB8, depending on whether the rotator is active. Since rotation requires tight integration between IC and IDMAC, I don't think the IRT should be represented as a separate media entity. The viewfinder task output pad would correspond to channel 21/CB1 or channel 49/CB9, and maybe in the future control whether to send that data off to the DMFC or to memory. The postprocessing input and output pads would go straight to memory and are not configurable, so I see no need to describe IC-PP as media entity. I'm not quite sure about the VDIC, but I guess that also should be configurable from userspace as one input to IC. For the deinterlacer to work, IC_INPUT needs to be set, so while this is active there is no way to route CSI0/1 through the IC directly. [...] No conflict here, there are different multiplexers to talk about. First, there are two external multiplexers controlled by IOMUXC (on i.MX6, these don't exist on i.MX5): MIPI_IPU1/2_MUX on i.MX6Q and IPU_CSI0/1_MUX. They are not part of the IPU. [...] right, this is one place where subdev linking makes sense to me. I.e. linking sensors to CSI ports. But you
[PATCH 16/30] [media] coda: add h.264 deblocking filter controls
This adds controls for the h.264 deblocking loop filter. Signed-off-by: Philipp Zabel p.za...@pengutronix.de --- drivers/media/platform/coda.c | 33 - 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index fa7eafb..4b84d16 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -161,6 +161,9 @@ struct coda_params { u8 h264_inter_qp; u8 h264_min_qp; u8 h264_max_qp; + u8 h264_deblk_enabled; + u8 h264_deblk_alpha; + u8 h264_deblk_beta; u8 mpeg4_intra_qp; u8 mpeg4_inter_qp; u8 gop_size; @@ -2380,7 +2383,17 @@ static int coda_start_encoding(struct coda_ctx *ctx) coda_write(dev, CODA9_STD_H264, CODA_CMD_ENC_SEQ_COD_STD); else coda_write(dev, CODA_STD_H264, CODA_CMD_ENC_SEQ_COD_STD); - coda_write(dev, 0, CODA_CMD_ENC_SEQ_264_PARA); + if (ctx-params.h264_deblk_enabled) { + value = ((ctx-params.h264_deblk_alpha + CODA_264PARAM_DEBLKFILTEROFFSETALPHA_MASK) +CODA_264PARAM_DEBLKFILTEROFFSETALPHA_OFFSET) | + ((ctx-params.h264_deblk_beta + CODA_264PARAM_DEBLKFILTEROFFSETBETA_MASK) +CODA_264PARAM_DEBLKFILTEROFFSETBETA_OFFSET); + } else { + value = 1 CODA_264PARAM_DISABLEDEBLK_OFFSET; + } + coda_write(dev, value, CODA_CMD_ENC_SEQ_264_PARA); break; default: v4l2_err(v4l2_dev, @@ -2691,6 +2704,16 @@ static int coda_s_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_MPEG_VIDEO_H264_MAX_QP: ctx-params.h264_max_qp = ctrl-val; break; + case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA: + ctx-params.h264_deblk_alpha = ctrl-val; + break; + case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA: + ctx-params.h264_deblk_beta = ctrl-val; + break; + case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE: + ctx-params.h264_deblk_enabled = (ctrl-val == + V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED); + break; case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP: ctx-params.mpeg4_intra_qp = ctrl-val; break; @@ -2745,6 +2768,14 @@ static int coda_ctrls_setup(struct coda_ctx *ctx) v4l2_ctrl_new_std(ctx-ctrls, coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_H264_MAX_QP, 0, 51, 1, 51); v4l2_ctrl_new_std(ctx-ctrls, coda_ctrl_ops, + V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA, 0, 15, 1, 0); + v4l2_ctrl_new_std(ctx-ctrls, coda_ctrl_ops, + V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA, 0, 15, 1, 0); + v4l2_ctrl_new_std_menu(ctx-ctrls, coda_ctrl_ops, + V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE, + V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED, 0x0, + V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED); + v4l2_ctrl_new_std(ctx-ctrls, coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP, 1, 31, 1, 2); v4l2_ctrl_new_std(ctx-ctrls, coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP, 1, 31, 1, 2); -- 2.0.0.rc2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 05/30] [media] coda: simplify IRAM setup
OVL and BTP IRAM buffers are never used, setup the bits for for DBK/BIT/IP usage depending on CODA version in one place. Also, use a simple allocator function and group IRAM addresses and size in a coda_aux_buf structure. This is done in preparation for CODA960 support. Signed-off-by: Philipp Zabel p.za...@pengutronix.de --- drivers/media/platform/coda.c | 175 ++ 1 file changed, 74 insertions(+), 101 deletions(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index 0384c9b..2b27998 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -135,9 +135,7 @@ struct coda_dev { struct coda_aux_buf tempbuf; struct coda_aux_buf workbuf; struct gen_pool *iram_pool; - long unsigned int iram_vaddr; - long unsigned int iram_paddr; - unsigned long iram_size; + struct coda_aux_buf iram; spinlock_t irqlock; struct mutexdev_mutex; @@ -175,6 +173,8 @@ struct coda_iram_info { phys_addr_t buf_btp_use; phys_addr_t search_ram_paddr; int search_ram_size; + int remaining; + phys_addr_t next_paddr; }; struct coda_ctx { @@ -1580,23 +1580,43 @@ static int coda_h264_padding(int size, char *p) return nal_size; } +static phys_addr_t coda_iram_alloc(struct coda_iram_info *iram, size_t size) +{ + phys_addr_t ret; + + size = round_up(size, 1024); + if (size iram-remaining) + return 0; + iram-remaining -= size; + + ret = iram-next_paddr; + iram-next_paddr += size; + + return ret; +} + static void coda_setup_iram(struct coda_ctx *ctx) { struct coda_iram_info *iram_info = ctx-iram_info; struct coda_dev *dev = ctx-dev; - int ipacdc_size; - int bitram_size; - int dbk_size; - int ovl_size; int mb_width; - int me_size; - int size; + int dbk_bits; + int bit_bits; + int ip_bits; memset(iram_info, 0, sizeof(*iram_info)); - size = dev-iram_size; + iram_info-next_paddr = dev-iram.paddr; + iram_info-remaining = dev-iram.size; - if (dev-devtype-product == CODA_DX6) + switch (dev-devtype-product) { + case CODA_7541: + dbk_bits = CODA7_USE_HOST_DBK_ENABLE | CODA7_USE_DBK_ENABLE; + bit_bits = CODA7_USE_HOST_BIT_ENABLE | CODA7_USE_BIT_ENABLE; + ip_bits = CODA7_USE_HOST_IP_ENABLE | CODA7_USE_IP_ENABLE; + break; + default: /* CODA_DX6 */ return; + } if (ctx-inst_type == CODA_INST_ENCODER) { struct coda_q_data *q_data_src; @@ -1605,111 +1625,63 @@ static void coda_setup_iram(struct coda_ctx *ctx) mb_width = DIV_ROUND_UP(q_data_src-width, 16); /* Prioritize in case IRAM is too small for everything */ - me_size = round_up(round_up(q_data_src-width, 16) * 36 + 2048, - 1024); - iram_info-search_ram_size = me_size; - if (size = iram_info-search_ram_size) { - if (dev-devtype-product == CODA_7541) - iram_info-axi_sram_use |= CODA7_USE_HOST_ME_ENABLE; - iram_info-search_ram_paddr = dev-iram_paddr; - size -= iram_info-search_ram_size; - } else { - pr_err(IRAM is smaller than the search ram size\n); - goto out; + if (dev-devtype-product == CODA_7541) { + iram_info-search_ram_size = round_up(mb_width * 16 * + 36 + 2048, 1024); + iram_info-search_ram_paddr = coda_iram_alloc(iram_info, + iram_info-search_ram_size); + if (!iram_info-search_ram_paddr) { + pr_err(IRAM is smaller than the search ram size\n); + goto out; + } + iram_info-axi_sram_use |= CODA7_USE_HOST_ME_ENABLE | + CODA7_USE_ME_ENABLE; } /* Only H.264BP and H.263P3 are considered */ - dbk_size = round_up(128 * mb_width, 1024); - if (size = dbk_size) { - iram_info-axi_sram_use |= CODA7_USE_HOST_DBK_ENABLE; - iram_info-buf_dbk_y_use = dev-iram_paddr + - iram_info-search_ram_size; - iram_info-buf_dbk_c_use = iram_info-buf_dbk_y_use + - dbk_size / 2; - size -=
[PATCH 07/30] [media] coda: add selection API support for h.264 decoder
The h.264 decoder produces capture frames that are a multiple of the macroblock size (16 pixels). To inform userspace about invalid pixel data at the edges, use the active and padded composing rectangles on the capture queue. The cropping information is obtained from the h.264 sequence parameter set. Signed-off-by: Philipp Zabel p.za...@pengutronix.de --- drivers/media/platform/coda.c | 87 +++ 1 file changed, 87 insertions(+) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index 10cc031..7e4df82 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -119,6 +119,7 @@ struct coda_q_data { unsigned intheight; unsigned intsizeimage; unsigned intfourcc; + struct v4l2_rectrect; }; struct coda_aux_buf { @@ -737,6 +738,10 @@ static int coda_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f) q_data-width = f-fmt.pix.width; q_data-height = f-fmt.pix.height; q_data-sizeimage = f-fmt.pix.sizeimage; + q_data-rect.left = 0; + q_data-rect.top = 0; + q_data-rect.width = f-fmt.pix.width; + q_data-rect.height = f-fmt.pix.height; v4l2_dbg(1, coda_debug, ctx-dev-v4l2_dev, Setting format for type %d, wxh: %dx%d, fmt: %d\n, @@ -873,6 +878,43 @@ static int coda_streamoff(struct file *file, void *priv, return ret; } +static int coda_g_selection(struct file *file, void *fh, + struct v4l2_selection *s) +{ + struct coda_ctx *ctx = fh_to_ctx(fh); + struct coda_q_data *q_data; + + switch (s-target) { + case V4L2_SEL_TGT_CROP: + q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); + s-r = q_data-rect; + break; + case V4L2_SEL_TGT_CROP_DEFAULT: + case V4L2_SEL_TGT_CROP_BOUNDS: + q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); + s-r.left = 0; + s-r.top = 0; + s-r.width = q_data-width; + s-r.height = q_data-height; + break; + case V4L2_SEL_TGT_COMPOSE: + case V4L2_SEL_TGT_COMPOSE_DEFAULT: + q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); + s-r = q_data-rect; + break; + case V4L2_SEL_TGT_COMPOSE_BOUNDS: + case V4L2_SEL_TGT_COMPOSE_PADDED: + q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); + s-r.left = 0; + s-r.top = 0; + s-r.width = q_data-width; + s-r.height = q_data-height; + break; + } + + return 0; +} + static int coda_try_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dc) { @@ -951,6 +993,8 @@ static const struct v4l2_ioctl_ops coda_ioctl_ops = { .vidioc_streamon= coda_streamon, .vidioc_streamoff = coda_streamoff, + .vidioc_g_selection = coda_g_selection, + .vidioc_try_decoder_cmd = coda_try_decoder_cmd, .vidioc_decoder_cmd = coda_decoder_cmd, @@ -1506,6 +1550,10 @@ static void set_default_params(struct coda_ctx *ctx) ctx-q_data[V4L2_M2M_DST].width = max_w; ctx-q_data[V4L2_M2M_DST].height = max_h; ctx-q_data[V4L2_M2M_DST].sizeimage = CODA_MAX_FRAME_SIZE; + ctx-q_data[V4L2_M2M_SRC].rect.width = max_w; + ctx-q_data[V4L2_M2M_SRC].rect.height = max_h; + ctx-q_data[V4L2_M2M_DST].rect.width = max_w; + ctx-q_data[V4L2_M2M_DST].rect.height = max_h; if (ctx-dev-devtype-product == CODA_960) coda_set_tiled_map_type(ctx, GDI_LINEAR_FRAME_MAP); @@ -2033,6 +2081,21 @@ static int coda_start_decoding(struct coda_ctx *ctx) return -EINVAL; } + if (src_fourcc == V4L2_PIX_FMT_H264) { + u32 left_right; + u32 top_bottom; + + left_right = coda_read(dev, CODA_RET_DEC_SEQ_CROP_LEFT_RIGHT); + top_bottom = coda_read(dev, CODA_RET_DEC_SEQ_CROP_TOP_BOTTOM); + + q_data_dst-rect.left = (left_right 10) 0x3ff; + q_data_dst-rect.top = (top_bottom 10) 0x3ff; + q_data_dst-rect.width = width - q_data_dst-rect.left - +(left_right 0x3ff); + q_data_dst-rect.height = height - q_data_dst-rect.top - + (top_bottom 0x3ff); + } + ret = coda_alloc_framebuffers(ctx, q_data_dst, src_fourcc); if (ret 0) return ret; @@ -2939,6 +3002,30 @@ static void coda_finish_decode(struct coda_ctx *ctx) q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); + /* frame crop information */ + if (src_fourcc == V4L2_PIX_FMT_H264) { + u32 left_right; + u32 top_bottom; + +
[PATCH 29/30] [media] coda: increase frame stride to 16 for h.264
When encoding into h.264, the input frame stride needs to be a multiple of 16. During allocation of the input buffers, it may not be known yet whether the encoder should create h.264 or not. Assume the worst and always use a frame stride that is a multiple of 16. Signed-off-by: Philipp Zabel p.za...@pengutronix.de --- drivers/media/platform/coda.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index c65047f..aabd639d 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -687,8 +687,8 @@ static int coda_try_fmt(struct coda_ctx *ctx, struct coda_codec *codec, switch (f-fmt.pix.pixelformat) { case V4L2_PIX_FMT_YUV420: case V4L2_PIX_FMT_YVU420: - /* Frame stride must be multiple of 8 */ - f-fmt.pix.bytesperline = round_up(f-fmt.pix.width, 8); + /* Frame stride must be multiple of 8, but 16 for h.264 */ + f-fmt.pix.bytesperline = round_up(f-fmt.pix.width, 16); f-fmt.pix.sizeimage = f-fmt.pix.bytesperline * f-fmt.pix.height * 3 / 2; break; -- 2.0.0.rc2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 04/30] [media] coda: fix internal framebuffer allocation size
This error was introduced by 5677e3b04d3b3961200aa2bb9cc715e709eafeb9 [media] coda: update CODA7541 to firmware 1.4.50. Signed-off-by: Philipp Zabel p.za...@pengutronix.de --- drivers/media/platform/coda.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index 544360e..0384c9b 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -1527,10 +1527,10 @@ static int coda_alloc_framebuffers(struct coda_ctx *ctx, struct coda_q_data *q_d for (i = 0; i ctx-num_internal_frames; i++) { size_t size; - size = q_data-sizeimage; + size = ysize + ysize / 2; if (ctx-codec-src_fourcc == V4L2_PIX_FMT_H264 dev-devtype-product != CODA_DX6) - ctx-internal_frames[i].size += ysize/4; + size += ysize / 4; ret = coda_alloc_context_buf(ctx, ctx-internal_frames[i], size); if (ret 0) { coda_free_framebuffers(ctx); -- 2.0.0.rc2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 24/30] [media] coda: use prescan_failed variable to stop stream after a timeout
This variable should be renamed to hold instead (temporarily stopping streaming until new data is fed into the bitstream buffer). Signed-off-by: Philipp Zabel p.za...@pengutronix.de --- drivers/media/platform/coda.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index 4641667dbc..a3fda5e 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -1477,6 +1477,8 @@ static void coda_pic_run_work(struct work_struct *work) if (!wait_for_completion_timeout(ctx-completion, msecs_to_jiffies(1000))) { dev_err(dev-plat_dev-dev, CODA PIC_RUN timeout\n); + + ctx-prescan_failed = true; } else if (!ctx-aborting) { if (ctx-inst_type == CODA_INST_DECODER) coda_finish_decode(ctx); -- 2.0.0.rc2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 14/30] [media] coda: select GENERIC_ALLOCATOR
The driver uses the genalloc API, which doesn't have stubs in case GENERIC_ALLOCATOR is disabled. Signed-off-by: Philipp Zabel p.za...@pengutronix.de --- drivers/media/platform/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 20f1655..1d2ac9d 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -140,6 +140,7 @@ config VIDEO_CODA select SRAM select VIDEOBUF2_DMA_CONTIG select V4L2_MEM2MEM_DEV + select GENERIC_ALLOCATOR ---help--- Coda is a range of video codec IPs that supports H.264, MPEG-4, and other video formats. -- 2.0.0.rc2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 27/30] [media] coda: allow odd width, but still round up bytesperline
Even though the CODA h.264 decoder always decodes complete macroblocks, we can set the stride to the corresponding multiple of 16 and use a value smaller than that as real width. Unfortunately the same doesn't work for height, as there is no vertical linesperframe stride for discontiguous planar YUV frames. Signed-off-by: Philipp Zabel p.za...@pengutronix.de --- drivers/media/platform/coda.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index 0697436..2b997bd 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -742,9 +742,9 @@ static int coda_try_fmt_vid_cap(struct file *file, void *priv, /* The h.264 decoder only returns complete 16x16 macroblocks */ if (codec codec-src_fourcc == V4L2_PIX_FMT_H264) { - f-fmt.pix.width = round_up(f-fmt.pix.width, 16); + f-fmt.pix.width = f-fmt.pix.width; f-fmt.pix.height = round_up(f-fmt.pix.height, 16); - f-fmt.pix.bytesperline = f-fmt.pix.width; + f-fmt.pix.bytesperline = round_up(f-fmt.pix.width, 16); f-fmt.pix.sizeimage = f-fmt.pix.bytesperline * f-fmt.pix.height * 3 / 2; } -- 2.0.0.rc2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 25/30] [media] coda: add reset control support
On i.MX53 and i.MX6, the CODA VPU can be reset by the System Reset Controller. We can use this to get out of dire situations, for example after a PIC_RUN timeout. Signed-off-by: Philipp Zabel p.za...@pengutronix.de --- drivers/media/platform/coda.c | 51 +++ 1 file changed, 51 insertions(+) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index a3fda5e..e71898e 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -27,6 +27,7 @@ #include linux/videodev2.h #include linux/of.h #include linux/platform_data/coda.h +#include linux/reset.h #include media/v4l2-ctrls.h #include media/v4l2-device.h @@ -138,6 +139,7 @@ struct coda_dev { void __iomem*regs_base; struct clk *clk_per; struct clk *clk_ahb; + struct reset_control*rstc; struct coda_aux_buf codebuf; struct coda_aux_buf tempbuf; @@ -337,6 +339,39 @@ static int coda_command_sync(struct coda_ctx *ctx, int cmd) return coda_wait_timeout(dev); } +static int coda_hw_reset(struct coda_ctx *ctx) +{ + struct coda_dev *dev = ctx-dev; + unsigned long timeout; + unsigned int idx; + int ret; + + if (!dev-rstc) + return -ENOENT; + + idx = coda_read(dev, CODA_REG_BIT_RUN_INDEX); + + timeout = jiffies + msecs_to_jiffies(100); + coda_write(dev, 0x11, CODA9_GDI_BUS_CTRL); + while (coda_read(dev, CODA9_GDI_BUS_STATUS) != 0x77) { + if (time_after(jiffies, timeout)) + return -ETIME; + cpu_relax(); + } + + ret = reset_control_reset(dev-rstc); + if (ret 0) + return ret; + + coda_write(dev, 0x00, CODA9_GDI_BUS_CTRL); + coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY); + coda_write(dev, CODA_REG_RUN_ENABLE, CODA_REG_BIT_CODE_RUN); + ret = coda_wait_timeout(dev); + coda_write(dev, idx, CODA_REG_BIT_RUN_INDEX); + + return ret; +} + static struct coda_q_data *get_q_data(struct coda_ctx *ctx, enum v4l2_buf_type type) { @@ -1479,6 +1514,8 @@ static void coda_pic_run_work(struct work_struct *work) dev_err(dev-plat_dev-dev, CODA PIC_RUN timeout\n); ctx-prescan_failed = true; + + coda_hw_reset(ctx); } else if (!ctx-aborting) { if (ctx-inst_type == CODA_INST_DECODER) coda_finish_decode(ctx); @@ -3387,6 +3424,9 @@ static int coda_hw_init(struct coda_dev *dev) if (ret) goto err_clk_ahb; + if (dev-rstc) + reset_control_reset(dev-rstc); + /* * Copy the first CODA_ISRAM_SIZE in the internal SRAM. * The 16-bit chars in the code buffer are in memory access @@ -3745,6 +3785,17 @@ static int coda_probe(struct platform_device *pdev) return -ENOENT; } + dev-rstc = devm_reset_control_get(pdev-dev, NULL); + if (IS_ERR(dev-rstc)) { + ret = PTR_ERR(dev-rstc); + if (ret == -ENOENT) { + dev-rstc = NULL; + } else { + dev_err(pdev-dev, failed get reset control: %d\n, ret); + return ret; + } + } + /* Get IRAM pool from device tree or platform data */ pool = of_get_named_gen_pool(np, iram, 0); if (!pool pdata) -- 2.0.0.rc2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 01/30] [media] coda: fix decoder I/P/B frame detection
Currently the rotator unit is used to copy decoded frames out into buffers provided by videobuf2. Since the CODA reports the I/P/B frame type of the last decoded frame, and this frame will be copied out in a later device_run, depending on display order, we have to store the frame type until such time. This patch also adds the B-frame type. Signed-off-by: Philipp Zabel p.za...@pengutronix.de --- drivers/media/platform/coda.c | 22 +- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index b178379..a69fa3b 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -209,6 +209,7 @@ struct coda_ctx { struct coda_aux_buf psbuf; struct coda_aux_buf slicebuf; struct coda_aux_buf internal_frames[CODA_MAX_FRAMEBUFFERS]; + u32 frame_types[CODA_MAX_FRAMEBUFFERS]; struct coda_aux_buf workbuf; int num_internal_frames; int idx; @@ -2693,15 +2694,6 @@ static void coda_finish_decode(struct coda_ctx *ctx) q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); - val = coda_read(dev, CODA_RET_DEC_PIC_TYPE); - if ((val 0x7) == 0) { - dst_buf-v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME; - dst_buf-v4l2_buf.flags = ~V4L2_BUF_FLAG_PFRAME; - } else { - dst_buf-v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME; - dst_buf-v4l2_buf.flags = ~V4L2_BUF_FLAG_KEYFRAME; - } - val = coda_read(dev, CODA_RET_DEC_PIC_ERR_MB); if (val 0) v4l2_err(dev-v4l2_dev, @@ -2748,6 +2740,14 @@ static void coda_finish_decode(struct coda_ctx *ctx) } else if (decoded_idx 0 || decoded_idx = ctx-num_internal_frames) { v4l2_err(dev-v4l2_dev, decoded frame index out of range: %d\n, decoded_idx); + } else { + val = coda_read(dev, CODA_RET_DEC_PIC_TYPE) 0x7; + if (val == 0) + ctx-frame_types[decoded_idx] = V4L2_BUF_FLAG_KEYFRAME; + else if (val == 1) + ctx-frame_types[decoded_idx] = V4L2_BUF_FLAG_PFRAME; + else + ctx-frame_types[decoded_idx] = V4L2_BUF_FLAG_BFRAME; } if (display_idx == -1) { @@ -2770,6 +2770,10 @@ static void coda_finish_decode(struct coda_ctx *ctx) dst_buf = v4l2_m2m_dst_buf_remove(ctx-m2m_ctx); dst_buf-v4l2_buf.sequence = ctx-osequence++; + dst_buf-v4l2_buf.flags = ~(V4L2_BUF_FLAG_KEYFRAME | +V4L2_BUF_FLAG_PFRAME); + dst_buf-v4l2_buf.flags |= ctx-frame_types[ctx-display_idx]; + vb2_set_plane_payload(dst_buf, 0, width * height * 3 / 2); v4l2_m2m_buf_done(dst_buf, success ? VB2_BUF_STATE_DONE : -- 2.0.0.rc2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 30/30] [media] coda: export auxiliary buffers via debugfs
This patch exports all auxiliary buffers, including SRAM, as debugfs binary blobs for debugging purposes. It shows, for example, that psbuf currently doesn't seem to be used at all on CODA7541, and that slicebuf and workbuf usage is far from the maximum. It can also be used to validate SRAM size allocation. Signed-off-by: Philipp Zabel p.za...@pengutronix.de --- drivers/media/platform/coda.c | 64 +++ 1 file changed, 53 insertions(+), 11 deletions(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index aabd639d..0b90087 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -12,6 +12,7 @@ */ #include linux/clk.h +#include linux/debugfs.h #include linux/delay.h #include linux/firmware.h #include linux/genalloc.h @@ -129,6 +130,8 @@ struct coda_aux_buf { void*vaddr; dma_addr_t paddr; u32 size; + struct debugfs_blob_wrapper blob; + struct dentry *dentry; }; struct coda_dev { @@ -156,6 +159,7 @@ struct coda_dev { struct vb2_alloc_ctx*alloc_ctx; struct list_headinstances; unsigned long instance_mask; + struct dentry *debugfs_root; }; struct coda_params { @@ -259,6 +263,7 @@ struct coda_ctx { u32 frm_dis_flg; u32 frame_mem_ctrl; int display_idx; + struct dentry *debugfs_entry; }; static const u8 coda_filler_nal[14] = { 0x00, 0x00, 0x00, 0x01, 0x0c, 0xff, @@ -1758,7 +1763,8 @@ static void coda_parabuf_write(struct coda_ctx *ctx, int index, u32 value) } static int coda_alloc_aux_buf(struct coda_dev *dev, - struct coda_aux_buf *buf, size_t size) + struct coda_aux_buf *buf, size_t size, + const char *name, struct dentry *parent) { buf-vaddr = dma_alloc_coherent(dev-plat_dev-dev, size, buf-paddr, GFP_KERNEL); @@ -1767,13 +1773,23 @@ static int coda_alloc_aux_buf(struct coda_dev *dev, buf-size = size; + if (name parent) { + buf-blob.data = buf-vaddr; + buf-blob.size = size; + buf-dentry = debugfs_create_blob(name, 0644, parent, buf-blob); + if (!buf-dentry) + dev_warn(dev-plat_dev-dev, +failed to create debugfs entry %s\n, name); + } + return 0; } static inline int coda_alloc_context_buf(struct coda_ctx *ctx, -struct coda_aux_buf *buf, size_t size) +struct coda_aux_buf *buf, size_t size, +const char *name) { - return coda_alloc_aux_buf(ctx-dev, buf, size); + return coda_alloc_aux_buf(ctx-dev, buf, size, name, ctx-debugfs_entry); } static void coda_free_aux_buf(struct coda_dev *dev, @@ -1785,6 +1801,7 @@ static void coda_free_aux_buf(struct coda_dev *dev, buf-vaddr = NULL; buf-size = 0; } + debugfs_remove(buf-dentry); } static void coda_free_framebuffers(struct coda_ctx *ctx) @@ -1817,12 +1834,16 @@ static int coda_alloc_framebuffers(struct coda_ctx *ctx, struct coda_q_data *q_d /* Allocate frame buffers */ for (i = 0; i ctx-num_internal_frames; i++) { size_t size; + char *name; size = ysize + ysize / 2; if (ctx-codec-src_fourcc == V4L2_PIX_FMT_H264 dev-devtype-product != CODA_DX6) size += ysize / 4; - ret = coda_alloc_context_buf(ctx, ctx-internal_frames[i], size); + name = kasprintf(GFP_KERNEL, fb%d, i); + ret = coda_alloc_context_buf(ctx, ctx-internal_frames[i], +size, name); + kfree(name); if (ret 0) { coda_free_framebuffers(ctx); return ret; @@ -2046,7 +2067,7 @@ static int coda_alloc_context_buffers(struct coda_ctx *ctx, /* worst case slice size */ size = (DIV_ROUND_UP(q_data-width, 16) * DIV_ROUND_UP(q_data-height, 16)) * 3200 / 8 + 512; - ret = coda_alloc_context_buf(ctx, ctx-slicebuf, size); + ret = coda_alloc_context_buf(ctx, ctx-slicebuf, size, slicebuf); if (ret 0) { v4l2_err(dev-v4l2_dev, failed to allocate %d byte slice buffer, ctx-slicebuf.size); @@ -2055,14 +2076,14 @@ static int coda_alloc_context_buffers(struct coda_ctx *ctx, } if (dev-devtype-product == CODA_7541) { -
[PATCH 02/30] [media] coda: fix readback of CODA_RET_DEC_SEQ_FRAME_NEED
Previously we'd add one to this value, allocating one additional, superfluous internal buffer. Signed-off-by: Philipp Zabel p.za...@pengutronix.de --- drivers/media/platform/coda.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index a69fa3b..453ac4b 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -1889,7 +1889,7 @@ static int coda_start_decoding(struct coda_ctx *ctx) v4l2_dbg(1, coda_debug, dev-v4l2_dev, %s instance %d now: %dx%d\n, __func__, ctx-idx, width, height); - ctx-num_internal_frames = coda_read(dev, CODA_RET_DEC_SEQ_FRAME_NEED) + 1; + ctx-num_internal_frames = coda_read(dev, CODA_RET_DEC_SEQ_FRAME_NEED); if (ctx-num_internal_frames CODA_MAX_FRAMEBUFFERS) { v4l2_err(dev-v4l2_dev, not enough framebuffers to decode (%d %d)\n, -- 2.0.0.rc2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 23/30] [media] coda: add sequence counter offset
The coda h.264 decoder also counts PIC_RUNs where no frame was decoded but a frame was rotated out / marked as ready to be displayed. This causes an offset between the incoming encoded frame's sequence number and the decode sequence number returned by the coda. This patch introduces a sequence counter offset variable to keep track of the difference. Signed-off-by: Philipp Zabel p.za...@pengutronix.de --- drivers/media/platform/coda.c | 11 --- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index 93836c8..4641667dbc 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -222,6 +222,7 @@ struct coda_ctx { u32 isequence; u32 qsequence; u32 osequence; + u32 sequence_offset; struct coda_q_data q_data[2]; enum coda_inst_type inst_type; struct coda_codec *codec; @@ -2674,6 +2675,7 @@ static void coda_stop_streaming(struct vb2_queue *q) ctx-streamon_cap = 0; ctx-osequence = 0; + ctx-sequence_offset = 0; } if (!ctx-streamon_out !ctx-streamon_cap) { @@ -3179,7 +3181,9 @@ static void coda_finish_decode(struct coda_ctx *ctx) if (decoded_idx == -1) { /* no frame was decoded, but we might have a display frame */ - if (display_idx 0 ctx-display_idx 0) + if (display_idx = 0 display_idx ctx-num_internal_frames) + ctx-sequence_offset++; + else if (ctx-display_idx 0) ctx-prescan_failed = true; } else if (decoded_idx == -2) { /* no frame was decoded, we still return the remaining buffers */ @@ -3191,10 +3195,11 @@ static void coda_finish_decode(struct coda_ctx *ctx) struct coda_timestamp, list); list_del(ts-list); val = coda_read(dev, CODA_RET_DEC_PIC_FRAME_NUM) - 1; + val -= ctx-sequence_offset; if (val != ts-sequence) { v4l2_err(dev-v4l2_dev, -sequence number mismatch (%d != %d)\n, -val, ts-sequence); +sequence number mismatch (%d(%d) != %d)\n, +val, ctx-sequence_offset, ts-sequence); } ctx-frame_timestamps[decoded_idx] = *ts; kfree(ts); -- 2.0.0.rc2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 21/30] [media] coda: add decoder timestamp queue
The coda driver advertises timestamp_type V4L2_BUF_FLAG_TIMESTAMP_COPY on both queues, so we have to copy timestamps from input v4l2 buffers to the corresponding destination v4l2 buffers. Since the h.264 decoder can reorder frames, a timestamp queue is needed to keep track of and assign the correct timestamp to destination buffers. Signed-off-by: Philipp Zabel p.za...@pengutronix.de --- drivers/media/platform/coda.c | 50 ++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index a00eaaf..9de0af0 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -201,6 +201,13 @@ struct gdi_tiled_map { #define GDI_LINEAR_FRAME_MAP 0 }; +struct coda_timestamp { + struct list_headlist; + u32 sequence; + struct v4l2_timecodetimecode; + struct timeval timestamp; +}; + struct coda_ctx { struct coda_dev *dev; struct mutexbuffer_mutex; @@ -235,6 +242,8 @@ struct coda_ctx { struct coda_aux_buf slicebuf; struct coda_aux_buf internal_frames[CODA_MAX_FRAMEBUFFERS]; u32 frame_types[CODA_MAX_FRAMEBUFFERS]; + struct coda_timestamp frame_timestamps[CODA_MAX_FRAMEBUFFERS]; + struct list_headtimestamp_list; struct coda_aux_buf workbuf; int num_internal_frames; int idx; @@ -1067,7 +1076,7 @@ static int coda_bitstream_queue(struct coda_ctx *ctx, struct vb2_buffer *src_buf dma_sync_single_for_device(ctx-dev-plat_dev-dev, ctx-bitstream.paddr, ctx-bitstream.size, DMA_TO_DEVICE); - ctx-qsequence++; + src_buf-v4l2_buf.sequence = ctx-qsequence++; return 0; } @@ -1103,12 +1112,26 @@ static bool coda_bitstream_try_queue(struct coda_ctx *ctx, static void coda_fill_bitstream(struct coda_ctx *ctx) { struct vb2_buffer *src_buf; + struct coda_timestamp *ts; while (v4l2_m2m_num_src_bufs_ready(ctx-fh.m2m_ctx) 0) { src_buf = v4l2_m2m_next_src_buf(ctx-fh.m2m_ctx); if (coda_bitstream_try_queue(ctx, src_buf)) { + /* +* Source buffer is queued in the bitstream ringbuffer; +* queue the timestamp and mark source buffer as done +*/ src_buf = v4l2_m2m_src_buf_remove(ctx-fh.m2m_ctx); + + ts = kmalloc(sizeof(*ts), GFP_KERNEL); + if (ts) { + ts-sequence = src_buf-v4l2_buf.sequence; + ts-timecode = src_buf-v4l2_buf.timecode; + ts-timestamp = src_buf-v4l2_buf.timestamp; + list_add_tail(ts-list, ctx-timestamp_list); + } + v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); } else { break; @@ -2653,6 +2676,14 @@ static void coda_stop_streaming(struct vb2_queue *q) } if (!ctx-streamon_out !ctx-streamon_cap) { + struct coda_timestamp *ts; + + while (!list_empty(ctx-timestamp_list)) { + ts = list_first_entry(ctx-timestamp_list, + struct coda_timestamp, list); + list_del(ts-list); + kfree(ts); + } kfifo_init(ctx-bitstream_fifo, ctx-bitstream.vaddr, ctx-bitstream.size); ctx-runcounter = 0; @@ -2940,6 +2971,7 @@ static int coda_open(struct file *file) ctx-bitstream.vaddr, ctx-bitstream.size); mutex_init(ctx-bitstream_mutex); mutex_init(ctx-buffer_mutex); + INIT_LIST_HEAD(ctx-timestamp_list); coda_lock(ctx); list_add(ctx-list, dev-instances); @@ -3031,6 +3063,7 @@ static void coda_finish_decode(struct coda_ctx *ctx) struct coda_q_data *q_data_src; struct coda_q_data *q_data_dst; struct vb2_buffer *dst_buf; + struct coda_timestamp *ts; int width, height; int decoded_idx; int display_idx; @@ -3152,6 +3185,18 @@ static void coda_finish_decode(struct coda_ctx *ctx) v4l2_err(dev-v4l2_dev, decoded frame index out of range: %d\n, decoded_idx); } else { + ts = list_first_entry(ctx-timestamp_list, + struct coda_timestamp, list); + list_del(ts-list); + val = coda_read(dev, CODA_RET_DEC_PIC_FRAME_NUM) - 1; + if (val != ts-sequence) { +
[PATCH 03/30] [media] coda: fix h.264 quantization parameter range
If bitrate is not set, the encoder is running in VBR mode, with the I- and P-frame quantization parameters configured from userspace. For the quantization parameters, 0 is a valid value. Signed-off-by: Philipp Zabel p.za...@pengutronix.de --- drivers/media/platform/coda.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index 453ac4b..544360e 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -2385,9 +2385,9 @@ static int coda_ctrls_setup(struct coda_ctx *ctx) v4l2_ctrl_new_std(ctx-ctrls, coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1, 60, 1, 16); v4l2_ctrl_new_std(ctx-ctrls, coda_ctrl_ops, - V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP, 1, 51, 1, 25); + V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP, 0, 51, 1, 25); v4l2_ctrl_new_std(ctx-ctrls, coda_ctrl_ops, - V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP, 1, 51, 1, 25); + V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP, 0, 51, 1, 25); v4l2_ctrl_new_std(ctx-ctrls, coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP, 1, 31, 1, 2); v4l2_ctrl_new_std(ctx-ctrls, coda_ctrl_ops, -- 2.0.0.rc2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 00/30] Initial CODA960 (i.MX6 VPU) support
Hi, the following series adds initial support for the CODA960 Video Processing Unit on i.MX6Q/D/DL/S SoCs to the coda driver. This series contains a few fixes and preparations, the CODA960 support patch, a rework of the hardware access serialization into a single threaded workqueue, some cleanups to use more infrastructure that is available in the meantime, runtime PM support, a few h.264 related v4l2 controls and fixes, support for hard resets via the i.MX system reset controller, and a patch that exports internal buffers to debugfs. regards Philipp Michael Olbrich (2): [media] v4l2-mem2mem: export v4l2_m2m_try_schedule [media] coda: try to schedule a decode run after a stop command Philipp Zabel (28): [media] coda: fix decoder I/P/B frame detection [media] coda: fix readback of CODA_RET_DEC_SEQ_FRAME_NEED [media] coda: fix h.264 quantization parameter range [media] coda: fix internal framebuffer allocation size [media] coda: simplify IRAM setup [media] coda: Add encoder/decoder support for CODA960 [media] coda: add selection API support for h.264 decoder [media] coda: add support for frame size enumeration [media] coda: add workqueue to serialize hardware commands [media] coda: Use mem-to-mem ioctl helpers [media] coda: use ctx-fh.m2m_ctx instead of ctx-m2m_ctx [media] coda: Add runtime pm support [media] coda: split firmware version check out of coda_hw_init [media] coda: select GENERIC_ALLOCATOR [media] coda: add h.264 min/max qp controls [media] coda: add h.264 deblocking filter controls [media] coda: add cyclic intra refresh control [media] coda: let userspace force IDR frames by enabling the keyframe flag in the source buffer [media] coda: add decoder timestamp queue [media] coda: alert userspace about macroblock errors [media] coda: add sequence counter offset [media] coda: use prescan_failed variable to stop stream after a timeout [media] coda: add reset control support [media] coda: add bytesperline to queue data [media] coda: allow odd width, but still round up bytesperline [media] coda: round up internal frames to multiples of macroblock size for h.264 [media] coda: increase frame stride to 16 for h.264 [media] coda: export auxiliary buffers via debugfs drivers/media/platform/Kconfig |1 + drivers/media/platform/coda.c | 1505 +++- drivers/media/platform/coda.h | 115 ++- drivers/media/v4l2-core/v4l2-mem2mem.c |3 +- include/media/v4l2-mem2mem.h |2 + 5 files changed, 1197 insertions(+), 429 deletions(-) -- 2.0.0.rc2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 26/30] [media] coda: add bytesperline to queue data
bytesperline is calculated in multiple places, store it in the coda_q_data structure. This will be more useful later when adding JPEG support. Signed-off-by: Philipp Zabel p.za...@pengutronix.de --- drivers/media/platform/coda.c | 25 ++--- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index e71898e..0697436 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -119,6 +119,7 @@ struct coda_devtype { struct coda_q_data { unsigned intwidth; unsigned intheight; + unsigned intbytesperline; unsigned intsizeimage; unsigned intfourcc; struct v4l2_rectrect; @@ -640,10 +641,7 @@ static int coda_g_fmt(struct file *file, void *priv, f-fmt.pix.pixelformat = q_data-fourcc; f-fmt.pix.width= q_data-width; f-fmt.pix.height = q_data-height; - if (coda_format_is_yuv(f-fmt.pix.pixelformat)) - f-fmt.pix.bytesperline = round_up(f-fmt.pix.width, 2); - else /* encoded formats h.264/mpeg4 */ - f-fmt.pix.bytesperline = 0; + f-fmt.pix.bytesperline = q_data-bytesperline; f-fmt.pix.sizeimage= q_data-sizeimage; f-fmt.pix.colorspace = ctx-colorspace; @@ -791,6 +789,7 @@ static int coda_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f) q_data-fourcc = f-fmt.pix.pixelformat; q_data-width = f-fmt.pix.width; q_data-height = f-fmt.pix.height; + q_data-bytesperline = f-fmt.pix.bytesperline; q_data-sizeimage = f-fmt.pix.sizeimage; q_data-rect.left = 0; q_data-rect.top = 0; @@ -1403,14 +1402,16 @@ static void coda_prepare_encode(struct coda_ctx *ctx) switch (q_data_src-fourcc) { case V4L2_PIX_FMT_YVU420: /* Switch Cb and Cr for YVU420 format */ - picture_cr = picture_y + q_data_src-width * q_data_src-height; - picture_cb = picture_cr + q_data_src-width / 2 * + picture_cr = picture_y + q_data_src-bytesperline * + q_data_src-height; + picture_cb = picture_cr + q_data_src-bytesperline / 2 * q_data_src-height / 2; break; case V4L2_PIX_FMT_YUV420: default: - picture_cb = picture_y + q_data_src-width * q_data_src-height; - picture_cr = picture_cb + q_data_src-width / 2 * + picture_cb = picture_y + q_data_src-bytesperline * + q_data_src-height; + picture_cr = picture_cb + q_data_src-bytesperline / 2 * q_data_src-height / 2; break; } @@ -2587,10 +2588,12 @@ static int coda_start_encoding(struct coda_ctx *ctx) } coda_write(dev, ctx-num_internal_frames, CODA_CMD_SET_FRAME_BUF_NUM); - coda_write(dev, round_up(q_data_src-width, 8), CODA_CMD_SET_FRAME_BUF_STRIDE); - if (dev-devtype-product == CODA_7541) - coda_write(dev, round_up(q_data_src-width, 8), + coda_write(dev, q_data_src-bytesperline, + CODA_CMD_SET_FRAME_BUF_STRIDE); + if (dev-devtype-product == CODA_7541) { + coda_write(dev, q_data_src-bytesperline, CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE); + } if (dev-devtype-product != CODA_DX6) { coda_write(dev, ctx-iram_info.buf_bit_use, CODA7_CMD_SET_FRAME_AXI_BIT_ADDR); -- 2.0.0.rc2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 28/30] [media] coda: round up internal frames to multiples of macroblock size for h.264
CODA7541 only supports encoding h.264 frames with width and height that are multiples of the macroblock size. Signed-off-by: Philipp Zabel p.za...@pengutronix.de --- drivers/media/platform/coda.c | 25 - 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index 2b997bd..c65047f 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -1798,15 +1798,21 @@ static void coda_free_framebuffers(struct coda_ctx *ctx) static int coda_alloc_framebuffers(struct coda_ctx *ctx, struct coda_q_data *q_data, u32 fourcc) { struct coda_dev *dev = ctx-dev; - int height = q_data-height; + int width, height; dma_addr_t paddr; int ysize; int ret; int i; - if (ctx-codec ctx-codec-src_fourcc == V4L2_PIX_FMT_H264) - height = round_up(height, 16); - ysize = round_up(q_data-width, 8) * height; + if (ctx-codec (ctx-codec-src_fourcc == V4L2_PIX_FMT_H264 || +ctx-codec-dst_fourcc == V4L2_PIX_FMT_H264)) { + width = round_up(q_data-width, 16); + height = round_up(q_data-height, 16); + } else { + width = round_up(q_data-width, 8); + height = q_data-height; + } + ysize = width * height; /* Allocate frame buffers */ for (i = 0; i ctx-num_internal_frames; i++) { @@ -2429,7 +2435,16 @@ static int coda_start_encoding(struct coda_ctx *ctx) value = (q_data_src-width CODADX6_PICWIDTH_MASK) CODADX6_PICWIDTH_OFFSET; value |= (q_data_src-height CODADX6_PICHEIGHT_MASK) CODA_PICHEIGHT_OFFSET; break; - default: + case CODA_7541: + if (dst_fourcc == V4L2_PIX_FMT_H264) { + value = (round_up(q_data_src-width, 16) +CODA7_PICWIDTH_MASK) CODA7_PICWIDTH_OFFSET; + value |= (round_up(q_data_src-height, 16) + CODA7_PICHEIGHT_MASK) CODA_PICHEIGHT_OFFSET; + break; + } + /* fallthrough */ + case CODA_960: value = (q_data_src-width CODA7_PICWIDTH_MASK) CODA7_PICWIDTH_OFFSET; value |= (q_data_src-height CODA7_PICHEIGHT_MASK) CODA_PICHEIGHT_OFFSET; } -- 2.0.0.rc2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 18/30] [media] coda: let userspace force IDR frames by enabling the keyframe flag in the source buffer
This disables forcing IDR frames at GOP size intervals on CODA7541 and CODA960, which is only needed to work around a firmware bug on CodaDx6. Instead, the V4L2_BUF_FLAG_KEYFRAME v4l2 buffer flag is cleared before marking the source buffer done for dequeueing. Userspace can set it before queueing a frame to force an IDR frame, to implement VFU (Video Fast Update). Signed-off-by: Philipp Zabel p.za...@pengutronix.de --- drivers/media/platform/coda.c | 18 ++ 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index 11e059d..cf75112 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -1264,22 +1264,22 @@ static void coda_prepare_encode(struct coda_ctx *ctx) * frame as IDR. This is a problem for some decoders that can't * recover when a frame is lost. */ - if (src_buf-v4l2_buf.sequence % ctx-params.gop_size) { - src_buf-v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME; - src_buf-v4l2_buf.flags = ~V4L2_BUF_FLAG_KEYFRAME; - } else { + if ((src_buf-v4l2_buf.sequence % ctx-params.gop_size) == 0) src_buf-v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME; + if (src_buf-v4l2_buf.flags V4L2_BUF_FLAG_KEYFRAME) src_buf-v4l2_buf.flags = ~V4L2_BUF_FLAG_PFRAME; - } + else + src_buf-v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME; if (dev-devtype-product == CODA_960) coda_set_gdi_regs(ctx); /* -* Copy headers at the beginning of the first frame for H.264 only. -* In MPEG4 they are already copied by the coda. +* Copy headers in front of the first frame and forced I frames for +* H.264 only. In MPEG4 they are already copied by the CODA. */ - if (src_buf-v4l2_buf.sequence == 0) { + if (src_buf-v4l2_buf.sequence == 0 || + src_buf-v4l2_buf.flags V4L2_BUF_FLAG_KEYFRAME) { pic_stream_buffer_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0) + ctx-vpu_header_size[0] + @@ -3245,6 +3245,8 @@ static void coda_finish_encode(struct coda_ctx *ctx) src_buf-v4l2_buf.flags V4L2_BUF_FLAG_TSTAMP_SRC_MASK; dst_buf-v4l2_buf.timecode = src_buf-v4l2_buf.timecode; + /* Clear keyframe flag so userspace can misuse it to force an IDR frame */ + src_buf-v4l2_buf.flags = ~V4L2_BUF_FLAG_KEYFRAME; v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); dst_buf = v4l2_m2m_dst_buf_remove(ctx-fh.m2m_ctx); -- 2.0.0.rc2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 06/30] [media] coda: Add encoder/decoder support for CODA960
This patch adds support for the CODA960 VPU in Freescale i.MX6 SoCs. It enables h.264 and MPEG4 encoding and decoding support. Besides the usual register shifting, the CODA960 gains frame memory control and GDI registers that are set up for linear mapping right now, needs ENC_PIC_SRC_INDEX to be set beyond the number of internal buffers for some reason, and has subsampling buffers that need to be set up. Also, the work buffer size is increased to 80 KiB. The CODA960 firmware spins if there is not enough input data in the bitstream buffer. To make it continue, buffers need to be copied into the bitstream as soon as they are queued. As the bitstream fifo is written into from two places, it must be protected with a mutex. For that, using a threaded interrupt handler is necessary. Signed-off-by: Philipp Zabel p.za...@pengutronix.de --- drivers/media/platform/coda.c | 397 +- drivers/media/platform/coda.h | 115 +++- 2 files changed, 464 insertions(+), 48 deletions(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index 2b27998..10cc031 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -44,19 +44,24 @@ #define CODA_FMO_BUF_SIZE 32 #define CODADX6_WORK_BUF_SIZE (288 * 1024 + CODA_FMO_BUF_SIZE * 8 * 1024) #define CODA7_WORK_BUF_SIZE(128 * 1024) +#define CODA9_WORK_BUF_SIZE(80 * 1024) #define CODA7_TEMP_BUF_SIZE(304 * 1024) +#define CODA9_TEMP_BUF_SIZE(204 * 1024) #define CODA_PARA_BUF_SIZE (10 * 1024) #define CODA_ISRAM_SIZE(2048 * 2) #define CODADX6_IRAM_SIZE 0xb000 #define CODA7_IRAM_SIZE0x14000 +#define CODA9_IRAM_SIZE0x21000 #define CODA7_PS_BUF_SIZE 0x28000 +#define CODA9_PS_SAVE_SIZE (512 * 1024) #define CODA_MAX_FRAMEBUFFERS 8 #define CODA_MAX_FRAME_SIZE0x10 #define FMO_SLICE_SAVE_BUF_SIZE (32) #define CODA_DEFAULT_GAMMA 4096 +#define CODA9_DEFAULT_GAMMA24576 /* 0.75 * 32768 */ #define MIN_W 176 #define MIN_H 144 @@ -84,6 +89,7 @@ enum coda_inst_type { enum coda_product { CODA_DX6 = 0xf001, CODA_7541 = 0xf012, + CODA_960 = 0xf020, }; struct coda_fmt { @@ -177,6 +183,16 @@ struct coda_iram_info { phys_addr_t next_paddr; }; +struct gdi_tiled_map { + int xy2ca_map[16]; + int xy2ba_map[16]; + int xy2ra_map[16]; + int rbc2axi_map[32]; + int xy2rbc_config; + int map_type; +#define GDI_LINEAR_FRAME_MAP 0 +}; + struct coda_ctx { struct coda_dev *dev; struct mutexbuffer_mutex; @@ -215,8 +231,10 @@ struct coda_ctx { int idx; int reg_idx; struct coda_iram_info iram_info; + struct gdi_tiled_maptiled_map; u32 bit_stream_param; u32 frm_dis_flg; + u32 frame_mem_ctrl; int display_idx; }; @@ -265,15 +283,23 @@ static void coda_command_async(struct coda_ctx *ctx, int cmd) { struct coda_dev *dev = ctx-dev; - if (dev-devtype-product == CODA_7541) { + if (dev-devtype-product == CODA_960 || + dev-devtype-product == CODA_7541) { /* Restore context related registers to CODA */ coda_write(dev, ctx-bit_stream_param, CODA_REG_BIT_BIT_STREAM_PARAM); coda_write(dev, ctx-frm_dis_flg, CODA_REG_BIT_FRM_DIS_FLG(ctx-reg_idx)); + coda_write(dev, ctx-frame_mem_ctrl, + CODA_REG_BIT_FRAME_MEM_CTRL); coda_write(dev, ctx-workbuf.paddr, CODA_REG_BIT_WORK_BUF_ADDR); } + if (dev-devtype-product == CODA_960) { + coda_write(dev, 1, CODA9_GDI_WPROT_ERR_CLR); + coda_write(dev, 0, CODA9_GDI_WPROT_RGN_EN); + } + coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY); coda_write(dev, ctx-idx, CODA_REG_BIT_RUN_INDEX); @@ -349,6 +375,13 @@ static struct coda_codec coda7_codecs[] = { CODA_CODEC(CODA7_MODE_DECODE_MP4, V4L2_PIX_FMT_MPEG4, V4L2_PIX_FMT_YUV420, 1920, 1080), }; +static struct coda_codec coda9_codecs[] = { + CODA_CODEC(CODA9_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264, 1920, 1080), + CODA_CODEC(CODA9_MODE_ENCODE_MP4, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_MPEG4, 1920, 1080), + CODA_CODEC(CODA9_MODE_DECODE_H264, V4L2_PIX_FMT_H264, V4L2_PIX_FMT_YUV420, 1920, 1080), + CODA_CODEC(CODA9_MODE_DECODE_MP4, V4L2_PIX_FMT_MPEG4, V4L2_PIX_FMT_YUV420, 1920, 1080), +}; + static bool coda_format_is_yuv(u32 fourcc) { switch (fourcc) { @@ -427,6 +460,8 @@ static char *coda_product_name(int
[PATCH 13/30] [media] coda: split firmware version check out of coda_hw_init
This adds a new function coda_check_firmware that does the firmware version checks so that this can be done only once from coda_probe instead of every time the runtime pm framework resumes the coda. Signed-off-by: Philipp Zabel p.za...@pengutronix.de --- drivers/media/platform/coda.c | 42 +- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index f39f693..b2e8e0e 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -3247,7 +3247,6 @@ static bool coda_firmware_supported(u32 vernum) static int coda_hw_init(struct coda_dev *dev) { - u16 product, major, minor, release; u32 data; u16 *p; int i, ret; @@ -3328,17 +3327,40 @@ static int coda_hw_init(struct coda_dev *dev) coda_write(dev, data, CODA_REG_BIT_CODE_RESET); coda_write(dev, CODA_REG_RUN_ENABLE, CODA_REG_BIT_CODE_RUN); - /* Load firmware */ + clk_disable_unprepare(dev-clk_ahb); + clk_disable_unprepare(dev-clk_per); + + return 0; + +err_clk_ahb: + clk_disable_unprepare(dev-clk_per); +err_clk_per: + return ret; +} + +static int coda_check_firmware(struct coda_dev *dev) +{ + u16 product, major, minor, release; + u32 data; + int ret; + + ret = clk_prepare_enable(dev-clk_per); + if (ret) + goto err_clk_per; + + ret = clk_prepare_enable(dev-clk_ahb); + if (ret) + goto err_clk_ahb; + coda_write(dev, 0, CODA_CMD_FIRMWARE_VERNUM); coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY); coda_write(dev, 0, CODA_REG_BIT_RUN_INDEX); coda_write(dev, 0, CODA_REG_BIT_RUN_COD_STD); coda_write(dev, CODA_COMMAND_FIRMWARE_GET, CODA_REG_BIT_RUN_COMMAND); if (coda_wait_timeout(dev)) { - clk_disable_unprepare(dev-clk_per); - clk_disable_unprepare(dev-clk_ahb); v4l2_err(dev-v4l2_dev, firmware get command error\n); - return -EIO; + ret = -EIO; + goto err_run_cmd; } if (dev-devtype-product == CODA_960) { @@ -3378,6 +3400,8 @@ static int coda_hw_init(struct coda_dev *dev) return 0; +err_run_cmd: + clk_disable_unprepare(dev-clk_ahb); err_clk_ahb: clk_disable_unprepare(dev-clk_per); err_clk_per: @@ -3418,6 +3442,10 @@ static void coda_fw_callback(const struct firmware *fw, void *context) return; } + ret = coda_check_firmware(dev); + if (ret 0) + return; + pm_runtime_put_sync(dev-plat_dev-dev); } else { /* @@ -3429,6 +3457,10 @@ static void coda_fw_callback(const struct firmware *fw, void *context) v4l2_err(dev-v4l2_dev, HW initialization failed\n); return; } + + ret = coda_check_firmware(dev); + if (ret 0) + return; } dev-vfd.fops = coda_fops, -- 2.0.0.rc2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 15/30] [media] coda: add h.264 min/max qp controls
If the bitrate control is set, the encoder works in CBR mode, dynamically changing the quantization parameters to achieve a constant bitrate. With the min/max QP controls the quantization parameters can be limited to a given range. Signed-off-by: Philipp Zabel p.za...@pengutronix.de --- drivers/media/platform/coda.c | 27 +++ 1 file changed, 27 insertions(+) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index b2e8e0e..fa7eafb 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -159,6 +159,8 @@ struct coda_params { u8 rot_mode; u8 h264_intra_qp; u8 h264_inter_qp; + u8 h264_min_qp; + u8 h264_max_qp; u8 mpeg4_intra_qp; u8 mpeg4_inter_qp; u8 gop_size; @@ -2433,7 +2435,16 @@ static int coda_start_encoding(struct coda_ctx *ctx) coda_write(dev, (gamma CODA_GAMMA_MASK) CODA_GAMMA_OFFSET, CODA_CMD_ENC_SEQ_RC_GAMMA); } + + if (ctx-params.h264_min_qp || ctx-params.h264_max_qp) { + coda_write(dev, + ctx-params.h264_min_qp CODA_QPMIN_OFFSET | + ctx-params.h264_max_qp CODA_QPMAX_OFFSET, + CODA_CMD_ENC_SEQ_RC_QP_MIN_MAX); + } if (dev-devtype-product == CODA_960) { + if (ctx-params.h264_max_qp) + value |= 1 CODA9_OPTION_RCQPMAX_OFFSET; if (CODA_DEFAULT_GAMMA 0) value |= 1 CODA9_OPTION_GAMMA_OFFSET; } else { @@ -2443,6 +2454,10 @@ static int coda_start_encoding(struct coda_ctx *ctx) else value |= 1 CODA7_OPTION_GAMMA_OFFSET; } + if (ctx-params.h264_min_qp) + value |= 1 CODA7_OPTION_RCQPMIN_OFFSET; + if (ctx-params.h264_max_qp) + value |= 1 CODA7_OPTION_RCQPMAX_OFFSET; } coda_write(dev, value, CODA_CMD_ENC_SEQ_OPTION); @@ -2670,6 +2685,12 @@ static int coda_s_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP: ctx-params.h264_inter_qp = ctrl-val; break; + case V4L2_CID_MPEG_VIDEO_H264_MIN_QP: + ctx-params.h264_min_qp = ctrl-val; + break; + case V4L2_CID_MPEG_VIDEO_H264_MAX_QP: + ctx-params.h264_max_qp = ctrl-val; + break; case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP: ctx-params.mpeg4_intra_qp = ctrl-val; break; @@ -2717,6 +2738,12 @@ static int coda_ctrls_setup(struct coda_ctx *ctx) V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP, 0, 51, 1, 25); v4l2_ctrl_new_std(ctx-ctrls, coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP, 0, 51, 1, 25); + if (ctx-dev-devtype-product != CODA_960) { + v4l2_ctrl_new_std(ctx-ctrls, coda_ctrl_ops, + V4L2_CID_MPEG_VIDEO_H264_MIN_QP, 0, 51, 1, 12); + } + v4l2_ctrl_new_std(ctx-ctrls, coda_ctrl_ops, + V4L2_CID_MPEG_VIDEO_H264_MAX_QP, 0, 51, 1, 51); v4l2_ctrl_new_std(ctx-ctrls, coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP, 1, 31, 1, 2); v4l2_ctrl_new_std(ctx-ctrls, coda_ctrl_ops, -- 2.0.0.rc2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 22/30] [media] coda: alert userspace about macroblock errors
If the CODA reports macroblock errors, also set the VB2_BUF_STATE_ERROR flag to alert userspace. Signed-off-by: Philipp Zabel p.za...@pengutronix.de --- drivers/media/platform/coda.c | 14 +- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index 9de0af0..93836c8 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -243,6 +243,7 @@ struct coda_ctx { struct coda_aux_buf internal_frames[CODA_MAX_FRAMEBUFFERS]; u32 frame_types[CODA_MAX_FRAMEBUFFERS]; struct coda_timestamp frame_timestamps[CODA_MAX_FRAMEBUFFERS]; + u32 frame_errors[CODA_MAX_FRAMEBUFFERS]; struct list_headtimestamp_list; struct coda_aux_buf workbuf; int num_internal_frames; @@ -3069,6 +3070,7 @@ static void coda_finish_decode(struct coda_ctx *ctx) int display_idx; u32 src_fourcc; int success; + u32 err_mb; u32 val; dst_buf = v4l2_m2m_next_dst_buf(ctx-fh.m2m_ctx); @@ -3138,10 +3140,10 @@ static void coda_finish_decode(struct coda_ctx *ctx) /* no cropping */ } - val = coda_read(dev, CODA_RET_DEC_PIC_ERR_MB); - if (val 0) + err_mb = coda_read(dev, CODA_RET_DEC_PIC_ERR_MB); + if (err_mb 0) v4l2_err(dev-v4l2_dev, -errors in %d macroblocks\n, val); +errors in %d macroblocks\n, err_mb); if (dev-devtype-product == CODA_7541) { val = coda_read(dev, CODA_RET_DEC_PIC_OPTION); @@ -3204,6 +3206,8 @@ static void coda_finish_decode(struct coda_ctx *ctx) ctx-frame_types[decoded_idx] = V4L2_BUF_FLAG_PFRAME; else ctx-frame_types[decoded_idx] = V4L2_BUF_FLAG_BFRAME; + + ctx-frame_errors[decoded_idx] = err_mb; } if (display_idx == -1) { @@ -3235,8 +3239,8 @@ static void coda_finish_decode(struct coda_ctx *ctx) vb2_set_plane_payload(dst_buf, 0, width * height * 3 / 2); - v4l2_m2m_buf_done(dst_buf, success ? VB2_BUF_STATE_DONE : -VB2_BUF_STATE_ERROR); + v4l2_m2m_buf_done(dst_buf, ctx-frame_errors[display_idx] ? + VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); v4l2_dbg(1, coda_debug, dev-v4l2_dev, job finished: decoding frame (%d) (%s)\n, -- 2.0.0.rc2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 09/30] [media] coda: add workqueue to serialize hardware commands
Using the coda_mutex lock to serialize hardware access would cause INFO: possible circular locking dependency detected lockdep warnings. Since the possible locking paths are hard to follow, serialize hardware access with a single workqueue thread. Ultimately the workqueue could be converted to only do register setup and readout for per-command work items. Using the initialized context property, SEQ_END is only queued in coda_release when needed. Signed-off-by: Philipp Zabel p.za...@pengutronix.de --- drivers/media/platform/coda.c | 162 +++--- 1 file changed, 74 insertions(+), 88 deletions(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index b5e5983..fe94acd 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -147,11 +147,11 @@ struct coda_dev { spinlock_t irqlock; struct mutexdev_mutex; struct mutexcoda_mutex; + struct workqueue_struct *workqueue; struct v4l2_m2m_dev *m2m_dev; struct vb2_alloc_ctx*alloc_ctx; struct list_headinstances; unsigned long instance_mask; - struct delayed_work timeout; }; struct coda_params { @@ -198,7 +198,9 @@ struct coda_ctx { struct coda_dev *dev; struct mutexbuffer_mutex; struct list_headlist; - struct work_struct skip_run; + struct work_struct pic_run_work; + struct work_struct seq_end_work; + struct completion completion; int aborting; int initialized; int streamon_out; @@ -1063,13 +1065,6 @@ static const struct v4l2_ioctl_ops coda_ioctl_ops = { static int coda_start_decoding(struct coda_ctx *ctx); -static void coda_skip_run(struct work_struct *work) -{ - struct coda_ctx *ctx = container_of(work, struct coda_ctx, skip_run); - - v4l2_m2m_job_finish(ctx-dev-m2m_dev, ctx-m2m_ctx); -} - static inline int coda_get_bitstream_payload(struct coda_ctx *ctx) { return kfifo_len(ctx-bitstream_fifo); @@ -1224,7 +1219,7 @@ static int coda_prepare_decode(struct coda_ctx *ctx) v4l2_dbg(1, coda_debug, dev-v4l2_dev, bitstream payload: %d, skipping\n, coda_get_bitstream_payload(ctx)); - schedule_work(ctx-skip_run); + v4l2_m2m_job_finish(ctx-dev-m2m_dev, ctx-m2m_ctx); return -EAGAIN; } @@ -1233,7 +1228,7 @@ static int coda_prepare_decode(struct coda_ctx *ctx) int ret = coda_start_decoding(ctx); if (ret 0) { v4l2_err(dev-v4l2_dev, failed to start decoding\n); - schedule_work(ctx-skip_run); + v4l2_m2m_job_finish(ctx-dev-m2m_dev, ctx-m2m_ctx); return -EAGAIN; } else { ctx-initialized = 1; @@ -1441,24 +1436,48 @@ static void coda_device_run(void *m2m_priv) { struct coda_ctx *ctx = m2m_priv; struct coda_dev *dev = ctx-dev; - int ret; + + queue_work(dev-workqueue, ctx-pic_run_work); +} + +static void coda_free_framebuffers(struct coda_ctx *ctx); +static void coda_free_context_buffers(struct coda_ctx *ctx); + +static void coda_seq_end_work(struct work_struct *work) +{ + struct coda_ctx *ctx = container_of(work, struct coda_ctx, seq_end_work); + struct coda_dev *dev = ctx-dev; mutex_lock(ctx-buffer_mutex); + mutex_lock(dev-coda_mutex); - /* -* If streamoff dequeued all buffers before we could get the lock, -* just bail out immediately. -*/ - if ((!v4l2_m2m_num_src_bufs_ready(ctx-m2m_ctx) - ctx-inst_type != CODA_INST_DECODER) || - !v4l2_m2m_num_dst_bufs_ready(ctx-m2m_ctx)) { - v4l2_dbg(1, coda_debug, dev-v4l2_dev, - %d: device_run without buffers\n, ctx-idx); - mutex_unlock(ctx-buffer_mutex); - schedule_work(ctx-skip_run); - return; + v4l2_dbg(1, coda_debug, dev-v4l2_dev, +%d: %s: sent command 'SEQ_END' to coda\n, ctx-idx, __func__); + if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) { + v4l2_err(dev-v4l2_dev, +CODA_COMMAND_SEQ_END failed\n); } + kfifo_init(ctx-bitstream_fifo, + ctx-bitstream.vaddr, ctx-bitstream.size); + + coda_free_framebuffers(ctx); + coda_free_context_buffers(ctx); + + mutex_unlock(dev-coda_mutex); + mutex_unlock(ctx-buffer_mutex); +} + +static void coda_finish_decode(struct coda_ctx *ctx); +static void coda_finish_encode(struct coda_ctx *ctx); + +static void
[PATCH 20/30] [media] coda: try to schedule a decode run after a stop command
From: Michael Olbrich m.olbr...@pengutronix.de In case no further buffers are queued after the stop command, restart job scheduling explicitly. Signed-off-by: Michael Olbrich m.olbr...@pengutronix.de Signed-off-by: Philipp Zabel p.za...@pengutronix.de --- drivers/media/platform/coda.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index cf75112..a00eaaf 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -904,6 +904,8 @@ static int coda_decoder_cmd(struct file *file, void *fh, /* If this context is currently running, update the hardware flag */ coda_write(dev, ctx-bit_stream_param, CODA_REG_BIT_BIT_STREAM_PARAM); } + ctx-prescan_failed = false; + v4l2_m2m_try_schedule(ctx-fh.m2m_ctx); return 0; } -- 2.0.0.rc2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 08/30] [media] coda: add support for frame size enumeration
This patch adds support for the VIDIOC_ENUM_FRAMESIZES ioctl. When decoding H.264, the output frame size is rounded up to the next multiple of the macroblock size (16 pixels). Signed-off-by: Philipp Zabel p.za...@pengutronix.de --- drivers/media/platform/coda.c | 59 +++ 1 file changed, 59 insertions(+) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index 7e4df82..b5e5983 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -958,6 +958,63 @@ static int coda_decoder_cmd(struct file *file, void *fh, return 0; } +static int coda_enum_framesizes(struct file *file, void *fh, + struct v4l2_frmsizeenum *fs) +{ + struct coda_ctx *ctx = fh_to_ctx(fh); + struct coda_q_data *q_data_src; + struct coda_codec *codec; + struct vb2_queue *src_vq; + int max_w; + int max_h; + int i; + + if (fs-index 0) + return -EINVAL; + + /* +* If the source format is already fixed, try to find a codec that +* converts to the given destination format +*/ + src_vq = v4l2_m2m_get_vq(ctx-m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); + if (vb2_is_streaming(src_vq)) { + q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); + + codec = coda_find_codec(ctx-dev, q_data_src-fourcc, + fs-pixel_format); + if (!codec) + return -EINVAL; + + fs-type = V4L2_FRMSIZE_TYPE_DISCRETE; + if (codec-src_fourcc == V4L2_PIX_FMT_H264) { + fs-discrete.width = round_up(q_data_src-width, 16); + fs-discrete.height = round_up(q_data_src-height, 16); + } else { + fs-discrete.width = q_data_src-width; + fs-discrete.height = q_data_src-height; + } + } else { + /* We don't know if input or output frame sizes are requested */ + coda_get_max_dimensions(ctx-dev, NULL, max_w, max_h); + fs-type = V4L2_FRMSIZE_TYPE_CONTINUOUS; + fs-stepwise.min_width = MIN_W; + fs-stepwise.max_width = max_w; + fs-stepwise.step_width = 1; + fs-stepwise.min_height = MIN_H; + fs-stepwise.max_height = max_h; + fs-stepwise.step_height = 1; + + for (i = 0; i ARRAY_SIZE(coda_formats); i++) { + if (coda_formats[i].fourcc == fs-pixel_format) + break; + } + if (i == ARRAY_SIZE(coda_formats)) + return -EINVAL; + } + + return 0; +} + static int coda_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub) { @@ -998,6 +1055,8 @@ static const struct v4l2_ioctl_ops coda_ioctl_ops = { .vidioc_try_decoder_cmd = coda_try_decoder_cmd, .vidioc_decoder_cmd = coda_decoder_cmd, + .vidioc_enum_framesizes = coda_enum_framesizes, + .vidioc_subscribe_event = coda_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; -- 2.0.0.rc2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 11/30] [media] coda: use ctx-fh.m2m_ctx instead of ctx-m2m_ctx
v4l2_fh already contains a mem2mem context pointer. Use it. Signed-off-by: Philipp Zabel p.za...@pengutronix.de --- drivers/media/platform/coda.c | 70 +-- 1 file changed, 34 insertions(+), 36 deletions(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index 52a429f..8321243 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -213,7 +213,6 @@ struct coda_ctx { struct coda_codec *codec; enum v4l2_colorspacecolorspace; struct coda_params params; - struct v4l2_m2m_ctx *m2m_ctx; struct v4l2_ctrl_handlerctrls; struct v4l2_fh fh; int gopcounter; @@ -554,7 +553,7 @@ static int coda_enum_fmt_vid_cap(struct file *file, void *priv, struct coda_q_data *q_data_src; /* If the source format is already fixed, only list matching formats */ - src_vq = v4l2_m2m_get_vq(ctx-m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); + src_vq = v4l2_m2m_get_vq(ctx-fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); if (vb2_is_streaming(src_vq)) { q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); @@ -578,7 +577,7 @@ static int coda_g_fmt(struct file *file, void *priv, struct coda_q_data *q_data; struct coda_ctx *ctx = fh_to_ctx(priv); - vq = v4l2_m2m_get_vq(ctx-m2m_ctx, f-type); + vq = v4l2_m2m_get_vq(ctx-fh.m2m_ctx, f-type); if (!vq) return -EINVAL; @@ -669,7 +668,7 @@ static int coda_try_fmt_vid_cap(struct file *file, void *priv, * If the source format is already fixed, try to find a codec that * converts to the given destination format */ - src_vq = v4l2_m2m_get_vq(ctx-m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); + src_vq = v4l2_m2m_get_vq(ctx-fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); if (vb2_is_streaming(src_vq)) { struct coda_q_data *q_data_src; @@ -723,7 +722,7 @@ static int coda_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f) struct coda_q_data *q_data; struct vb2_queue *vq; - vq = v4l2_m2m_get_vq(ctx-m2m_ctx, f-type); + vq = v4l2_m2m_get_vq(ctx-fh.m2m_ctx, f-type); if (!vq) return -EINVAL; @@ -787,7 +786,7 @@ static int coda_qbuf(struct file *file, void *priv, { struct coda_ctx *ctx = fh_to_ctx(priv); - return v4l2_m2m_qbuf(file, ctx-m2m_ctx, buf); + return v4l2_m2m_qbuf(file, ctx-fh.m2m_ctx, buf); } static bool coda_buf_is_end_of_stream(struct coda_ctx *ctx, @@ -795,7 +794,7 @@ static bool coda_buf_is_end_of_stream(struct coda_ctx *ctx, { struct vb2_queue *src_vq; - src_vq = v4l2_m2m_get_vq(ctx-m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); + src_vq = v4l2_m2m_get_vq(ctx-fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); return ((ctx-bit_stream_param CODA_BIT_STREAM_END_FLAG) (buf-sequence == (ctx-qsequence - 1))); @@ -807,7 +806,7 @@ static int coda_dqbuf(struct file *file, void *priv, struct coda_ctx *ctx = fh_to_ctx(priv); int ret; - ret = v4l2_m2m_dqbuf(file, ctx-m2m_ctx, buf); + ret = v4l2_m2m_dqbuf(file, ctx-fh.m2m_ctx, buf); /* If this is the last capture buffer, emit an end-of-stream event */ if (buf-type == V4L2_BUF_TYPE_VIDEO_CAPTURE @@ -920,7 +919,7 @@ static int coda_enum_framesizes(struct file *file, void *fh, * If the source format is already fixed, try to find a codec that * converts to the given destination format */ - src_vq = v4l2_m2m_get_vq(ctx-m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); + src_vq = v4l2_m2m_get_vq(ctx-fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); if (vb2_is_streaming(src_vq)) { q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); @@ -1096,11 +1095,11 @@ static void coda_fill_bitstream(struct coda_ctx *ctx) { struct vb2_buffer *src_buf; - while (v4l2_m2m_num_src_bufs_ready(ctx-m2m_ctx) 0) { - src_buf = v4l2_m2m_next_src_buf(ctx-m2m_ctx); + while (v4l2_m2m_num_src_bufs_ready(ctx-fh.m2m_ctx) 0) { + src_buf = v4l2_m2m_next_src_buf(ctx-fh.m2m_ctx); if (coda_bitstream_try_queue(ctx, src_buf)) { - src_buf = v4l2_m2m_src_buf_remove(ctx-m2m_ctx); + src_buf = v4l2_m2m_src_buf_remove(ctx-fh.m2m_ctx); v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); } else { break; @@ -1140,7 +1139,7 @@ static int coda_prepare_decode(struct coda_ctx *ctx) u32 stridey, height; u32 picture_y, picture_cb, picture_cr; - dst_buf = v4l2_m2m_next_dst_buf(ctx-m2m_ctx); + dst_buf = v4l2_m2m_next_dst_buf(ctx-fh.m2m_ctx); q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
[PATCH 19/30] [media] v4l2-mem2mem: export v4l2_m2m_try_schedule
From: Michael Olbrich m.olbr...@pengutronix.de Some drivers might allow to decode remaining frames from an internal ringbuffer after a decoder stop command. Allow those to call v4l2_m2m_try_schedule directly. Signed-off-by: Michael Olbrich m.olbr...@pengutronix.de Signed-off-by: Philipp Zabel p.za...@pengutronix.de --- drivers/media/v4l2-core/v4l2-mem2mem.c | 3 ++- include/media/v4l2-mem2mem.h | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c index 178ce96..5f5c175 100644 --- a/drivers/media/v4l2-core/v4l2-mem2mem.c +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c @@ -208,7 +208,7 @@ static void v4l2_m2m_try_run(struct v4l2_m2m_dev *m2m_dev) * An example of the above could be an instance that requires more than one * src/dst buffer per transaction. */ -static void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx) +void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx) { struct v4l2_m2m_dev *m2m_dev; unsigned long flags_job, flags_out, flags_cap; @@ -274,6 +274,7 @@ static void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx) v4l2_m2m_try_run(m2m_dev); } +EXPORT_SYMBOL(v4l2_m2m_try_schedule); /** * v4l2_m2m_cancel_job() - cancel pending jobs for the context diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h index 12ea5a6..c5f3914 100644 --- a/include/media/v4l2-mem2mem.h +++ b/include/media/v4l2-mem2mem.h @@ -95,6 +95,8 @@ void *v4l2_m2m_get_curr_priv(struct v4l2_m2m_dev *m2m_dev); struct vb2_queue *v4l2_m2m_get_vq(struct v4l2_m2m_ctx *m2m_ctx, enum v4l2_buf_type type); +void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx); + void v4l2_m2m_job_finish(struct v4l2_m2m_dev *m2m_dev, struct v4l2_m2m_ctx *m2m_ctx); -- 2.0.0.rc2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 12/30] [media] coda: Add runtime pm support
This patch allows to use the runtime pm and generic pm domain frameworks to completely gate power to the VPU if it is unused. This functionality is available on i.MX6. Signed-off-by: Philipp Zabel p.za...@pengutronix.de --- drivers/media/platform/coda.c | 65 +++ 1 file changed, 60 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index 8321243..f39f693 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -22,6 +22,7 @@ #include linux/module.h #include linux/of_device.h #include linux/platform_device.h +#include linux/pm_runtime.h #include linux/slab.h #include linux/videodev2.h #include linux/of.h @@ -2820,6 +2821,13 @@ static int coda_open(struct file *file) ctx-reg_idx = idx; } + /* Power up and upload firmware if necessary */ + ret = pm_runtime_get_sync(dev-plat_dev-dev); + if (ret 0) { + v4l2_err(dev-v4l2_dev, failed to power up: %d\n, ret); + goto err_pm_get; + } + ret = clk_prepare_enable(dev-clk_per); if (ret) goto err_clk_per; @@ -2889,6 +2897,8 @@ err_ctx_init: err_clk_ahb: clk_disable_unprepare(dev-clk_per); err_clk_per: + pm_runtime_put_sync(dev-plat_dev-dev); +err_pm_get: v4l2_fh_del(ctx-fh); v4l2_fh_exit(ctx-fh); clear_bit(ctx-idx, dev-instance_mask); @@ -2930,6 +2940,7 @@ static int coda_release(struct file *file) v4l2_ctrl_handler_free(ctx-ctrls); clk_disable_unprepare(dev-clk_ahb); clk_disable_unprepare(dev-clk_per); + pm_runtime_put_sync(dev-plat_dev-dev); v4l2_fh_del(ctx-fh); v4l2_fh_exit(ctx-fh); clear_bit(ctx-idx, dev-instance_mask); @@ -3243,7 +3254,7 @@ static int coda_hw_init(struct coda_dev *dev) ret = clk_prepare_enable(dev-clk_per); if (ret) - return ret; + goto err_clk_per; ret = clk_prepare_enable(dev-clk_ahb); if (ret) @@ -3369,6 +3380,7 @@ static int coda_hw_init(struct coda_dev *dev) err_clk_ahb: clk_disable_unprepare(dev-clk_per); +err_clk_per: return ret; } @@ -3394,10 +3406,29 @@ static void coda_fw_callback(const struct firmware *fw, void *context) memcpy(dev-codebuf.vaddr, fw-data, fw-size); release_firmware(fw); - ret = coda_hw_init(dev); - if (ret) { - v4l2_err(dev-v4l2_dev, HW initialization failed\n); - return; + if (IS_ENABLED(CONFIG_PM_RUNTIME) pdev-dev.pm_domain) { + /* +* Enabling power temporarily will cause coda_hw_init to be +* called via coda_runtime_resume by the pm domain. +*/ + ret = pm_runtime_get_sync(dev-plat_dev-dev); + if (ret 0) { + v4l2_err(dev-v4l2_dev, failed to power on: %d\n, +ret); + return; + } + + pm_runtime_put_sync(dev-plat_dev-dev); + } else { + /* +* If runtime pm is disabled or pm_domain is not set, +* initialize once manually. +*/ + ret = coda_hw_init(dev); + if (ret 0) { + v4l2_err(dev-v4l2_dev, HW initialization failed\n); + return; + } } dev-vfd.fops = coda_fops, @@ -3635,6 +3666,8 @@ static int coda_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dev); + pm_runtime_enable(pdev-dev); + return coda_firmware_request(dev); } @@ -3645,6 +3678,7 @@ static int coda_remove(struct platform_device *pdev) video_unregister_device(dev-vfd); if (dev-m2m_dev) v4l2_m2m_release(dev-m2m_dev); + pm_runtime_disable(pdev-dev); if (dev-alloc_ctx) vb2_dma_contig_cleanup_ctx(dev-alloc_ctx); v4l2_device_unregister(dev-v4l2_dev); @@ -3658,6 +3692,26 @@ static int coda_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM_RUNTIME +static int coda_runtime_resume(struct device *dev) +{ + struct coda_dev *cdev = dev_get_drvdata(dev); + int ret = 0; + + if (dev-pm_domain) { + ret = coda_hw_init(cdev); + if (ret) + v4l2_err(cdev-v4l2_dev, HW initialization failed\n); + } + + return ret; +} +#endif + +static const struct dev_pm_ops coda_pm_ops = { + SET_RUNTIME_PM_OPS(NULL, coda_runtime_resume, NULL) +}; + static struct platform_driver coda_driver = { .probe = coda_probe, .remove = coda_remove, @@ -3665,6 +3719,7 @@ static struct platform_driver coda_driver = { .name = CODA_NAME, .owner = THIS_MODULE, .of_match_table =
[PATCH 17/30] [media] coda: add cyclic intra refresh control
Allow userspace to enable cyclic intra refresh by setting the number of intra macroblocks per frame to a non-zero value. Signed-off-by: Philipp Zabel p.za...@pengutronix.de --- drivers/media/platform/coda.c | 9 - 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index 4b84d16..11e059d 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -167,6 +167,7 @@ struct coda_params { u8 mpeg4_intra_qp; u8 mpeg4_inter_qp; u8 gop_size; + int intra_refresh; int codec_mode; int codec_mode_aux; enum v4l2_mpeg_video_multi_slice_mode slice_mode; @@ -2433,7 +2434,8 @@ static int coda_start_encoding(struct coda_ctx *ctx) coda_write(dev, value, CODA_CMD_ENC_SEQ_RC_PARA); coda_write(dev, 0, CODA_CMD_ENC_SEQ_RC_BUF_SIZE); - coda_write(dev, 0, CODA_CMD_ENC_SEQ_INTRA_REFRESH); + coda_write(dev, ctx-params.intra_refresh, + CODA_CMD_ENC_SEQ_INTRA_REFRESH); coda_write(dev, bitstream_buf, CODA_CMD_ENC_SEQ_BB_START); coda_write(dev, bitstream_size / 1024, CODA_CMD_ENC_SEQ_BB_SIZE); @@ -2731,6 +2733,9 @@ static int coda_s_ctrl(struct v4l2_ctrl *ctrl) break; case V4L2_CID_MPEG_VIDEO_HEADER_MODE: break; + case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB: + ctx-params.intra_refresh = ctrl-val; + break; default: v4l2_dbg(1, coda_debug, ctx-dev-v4l2_dev, Invalid control, id=%d, val=%d\n, @@ -2792,6 +2797,8 @@ static int coda_ctrls_setup(struct coda_ctx *ctx) V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME, (1 V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE), V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME); + v4l2_ctrl_new_std(ctx-ctrls, coda_ctrl_ops, + V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB, 0, 1920 * 1088 / 256, 1, 0); if (ctx-ctrls.error) { v4l2_err(ctx-dev-v4l2_dev, control initialization error (%d), -- 2.0.0.rc2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 10/30] [media] coda: Use mem-to-mem ioctl helpers
Use the mem2mem helpers introduced to get rid of some duplicated code. Signed-off-by: Philipp Zabel p.za...@pengutronix.de --- drivers/media/platform/coda.c | 113 ++ 1 file changed, 14 insertions(+), 99 deletions(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index fe94acd..52a429f 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -782,22 +782,6 @@ static int coda_s_fmt_vid_out(struct file *file, void *priv, return ret; } -static int coda_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *reqbufs) -{ - struct coda_ctx *ctx = fh_to_ctx(priv); - - return v4l2_m2m_reqbufs(file, ctx-m2m_ctx, reqbufs); -} - -static int coda_querybuf(struct file *file, void *priv, -struct v4l2_buffer *buf) -{ - struct coda_ctx *ctx = fh_to_ctx(priv); - - return v4l2_m2m_querybuf(file, ctx-m2m_ctx, buf); -} - static int coda_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { @@ -806,14 +790,6 @@ static int coda_qbuf(struct file *file, void *priv, return v4l2_m2m_qbuf(file, ctx-m2m_ctx, buf); } -static int coda_expbuf(struct file *file, void *priv, - struct v4l2_exportbuffer *eb) -{ - struct coda_ctx *ctx = fh_to_ctx(priv); - - return v4l2_m2m_expbuf(file, ctx-m2m_ctx, eb); -} - static bool coda_buf_is_end_of_stream(struct coda_ctx *ctx, struct v4l2_buffer *buf) { @@ -846,40 +822,6 @@ static int coda_dqbuf(struct file *file, void *priv, return ret; } -static int coda_create_bufs(struct file *file, void *priv, - struct v4l2_create_buffers *create) -{ - struct coda_ctx *ctx = fh_to_ctx(priv); - - return v4l2_m2m_create_bufs(file, ctx-m2m_ctx, create); -} - -static int coda_streamon(struct file *file, void *priv, -enum v4l2_buf_type type) -{ - struct coda_ctx *ctx = fh_to_ctx(priv); - - return v4l2_m2m_streamon(file, ctx-m2m_ctx, type); -} - -static int coda_streamoff(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct coda_ctx *ctx = fh_to_ctx(priv); - int ret; - - /* -* This indirectly calls __vb2_queue_cancel, which dequeues all buffers. -* We therefore have to lock it against running hardware in this context, -* which still needs the buffers. -*/ - mutex_lock(ctx-buffer_mutex); - ret = v4l2_m2m_streamoff(file, ctx-m2m_ctx, type); - mutex_unlock(ctx-buffer_mutex); - - return ret; -} - static int coda_g_selection(struct file *file, void *fh, struct v4l2_selection *s) { @@ -1041,16 +983,16 @@ static const struct v4l2_ioctl_ops coda_ioctl_ops = { .vidioc_try_fmt_vid_out = coda_try_fmt_vid_out, .vidioc_s_fmt_vid_out = coda_s_fmt_vid_out, - .vidioc_reqbufs = coda_reqbufs, - .vidioc_querybuf= coda_querybuf, + .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, + .vidioc_querybuf= v4l2_m2m_ioctl_querybuf, .vidioc_qbuf= coda_qbuf, - .vidioc_expbuf = coda_expbuf, + .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, .vidioc_dqbuf = coda_dqbuf, - .vidioc_create_bufs = coda_create_bufs, + .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, - .vidioc_streamon= coda_streamon, - .vidioc_streamoff = coda_streamoff, + .vidioc_streamon= v4l2_m2m_ioctl_streamon, + .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, .vidioc_g_selection = coda_g_selection, @@ -1731,18 +1673,6 @@ static void coda_buf_queue(struct vb2_buffer *vb) } } -static void coda_wait_prepare(struct vb2_queue *q) -{ - struct coda_ctx *ctx = vb2_get_drv_priv(q); - coda_unlock(ctx); -} - -static void coda_wait_finish(struct vb2_queue *q) -{ - struct coda_ctx *ctx = vb2_get_drv_priv(q); - coda_lock(ctx); -} - static void coda_parabuf_write(struct coda_ctx *ctx, int index, u32 value) { struct coda_dev *dev = ctx-dev; @@ -2701,10 +2631,10 @@ static struct vb2_ops coda_qops = { .queue_setup= coda_queue_setup, .buf_prepare= coda_buf_prepare, .buf_queue = coda_buf_queue, - .wait_prepare = coda_wait_prepare, - .wait_finish= coda_wait_finish, .start_streaming= coda_start_streaming, .stop_streaming = coda_stop_streaming, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish= vb2_ops_wait_finish, }; static int coda_s_ctrl(struct v4l2_ctrl *ctrl) @@ -2827,6 +2757,7 @@ static int coda_queue_init(void *priv, struct vb2_queue *src_vq,
Re: [PATCH 12/30] [media] coda: Add runtime pm support
Hello Philipp, On 13/06/14 18:08, Philipp Zabel wrote: This patch allows to use the runtime pm and generic pm domain frameworks to completely gate power to the VPU if it is unused. This functionality is available on i.MX6. Signed-off-by: Philipp Zabel p.za...@pengutronix.de --- drivers/media/platform/coda.c | 65 +++ 1 file changed, 60 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index 8321243..f39f693 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -22,6 +22,7 @@ #include linux/module.h #include linux/of_device.h #include linux/platform_device.h +#include linux/pm_runtime.h #include linux/slab.h #include linux/videodev2.h #include linux/of.h @@ -2820,6 +2821,13 @@ static int coda_open(struct file *file) ctx-reg_idx = idx; } + /* Power up and upload firmware if necessary */ + ret = pm_runtime_get_sync(dev-plat_dev-dev); + if (ret 0) { + v4l2_err(dev-v4l2_dev, failed to power up: %d\n, ret); + goto err_pm_get; + } + ret = clk_prepare_enable(dev-clk_per); if (ret) goto err_clk_per; @@ -2889,6 +2897,8 @@ err_ctx_init: err_clk_ahb: clk_disable_unprepare(dev-clk_per); err_clk_per: + pm_runtime_put_sync(dev-plat_dev-dev); +err_pm_get: v4l2_fh_del(ctx-fh); v4l2_fh_exit(ctx-fh); clear_bit(ctx-idx, dev-instance_mask); @@ -2930,6 +2940,7 @@ static int coda_release(struct file *file) v4l2_ctrl_handler_free(ctx-ctrls); clk_disable_unprepare(dev-clk_ahb); clk_disable_unprepare(dev-clk_per); + pm_runtime_put_sync(dev-plat_dev-dev); v4l2_fh_del(ctx-fh); v4l2_fh_exit(ctx-fh); clear_bit(ctx-idx, dev-instance_mask); @@ -3243,7 +3254,7 @@ static int coda_hw_init(struct coda_dev *dev) ret = clk_prepare_enable(dev-clk_per); if (ret) - return ret; + goto err_clk_per; ret = clk_prepare_enable(dev-clk_ahb); if (ret) @@ -3369,6 +3380,7 @@ static int coda_hw_init(struct coda_dev *dev) err_clk_ahb: clk_disable_unprepare(dev-clk_per); +err_clk_per: return ret; } @@ -3394,10 +3406,29 @@ static void coda_fw_callback(const struct firmware *fw, void *context) memcpy(dev-codebuf.vaddr, fw-data, fw-size); release_firmware(fw); - ret = coda_hw_init(dev); - if (ret) { - v4l2_err(dev-v4l2_dev, HW initialization failed\n); - return; + if (IS_ENABLED(CONFIG_PM_RUNTIME) pdev-dev.pm_domain) { How about using the pm_runtime_enabled() helper ? Also why do you need to be checking dev.pm_domain here and in the resume() callback ? Couldn't it be done unconditionally ? Why the driver needs to care about the PM domain existence ? + /* + * Enabling power temporarily will cause coda_hw_init to be + * called via coda_runtime_resume by the pm domain. + */ + ret = pm_runtime_get_sync(dev-plat_dev-dev); + if (ret 0) { + v4l2_err(dev-v4l2_dev, failed to power on: %d\n, + ret); + return; + } + + pm_runtime_put_sync(dev-plat_dev-dev); + } else { + /* + * If runtime pm is disabled or pm_domain is not set, + * initialize once manually. + */ + ret = coda_hw_init(dev); + if (ret 0) { + v4l2_err(dev-v4l2_dev, HW initialization failed\n); + return; + } } dev-vfd.fops = coda_fops, @@ -3635,6 +3666,8 @@ static int coda_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dev); + pm_runtime_enable(pdev-dev); + return coda_firmware_request(dev); } @@ -3645,6 +3678,7 @@ static int coda_remove(struct platform_device *pdev) video_unregister_device(dev-vfd); if (dev-m2m_dev) v4l2_m2m_release(dev-m2m_dev); + pm_runtime_disable(pdev-dev); if (dev-alloc_ctx) vb2_dma_contig_cleanup_ctx(dev-alloc_ctx); v4l2_device_unregister(dev-v4l2_dev); @@ -3658,6 +3692,26 @@ static int coda_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM_RUNTIME +static int coda_runtime_resume(struct device *dev) +{ + struct coda_dev *cdev = dev_get_drvdata(dev); + int ret = 0; + + if (dev-pm_domain) { + ret = coda_hw_init(cdev); + if (ret) + v4l2_err(cdev-v4l2_dev, HW initialization failed\n); + } + + return ret; +} +#endif -- Regards, Sylwester -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to
Re: [patch v2] [media] davinci: vpif: missing unlocks on error
On Thu, Jun 12, 2014 at 8:01 AM, Dan Carpenter dan.carpen...@oracle.com wrote: We recently changed some locking around so we need some new unlocks on the error paths. Signed-off-by: Dan Carpenter dan.carpen...@oracle.com Applied! Thanks, --Prabhakar Lad --- v2: move the unlock so the list_for_each_entry_safe() loop is protected diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index a7ed164..1e4ec69 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c @@ -269,6 +269,7 @@ err: list_del(buf-list); vb2_buffer_done(buf-vb, VB2_BUF_STATE_QUEUED); } + spin_unlock_irqrestore(common-irqlock, flags); return ret; } diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index 5bb085b..b431b58 100644 --- a/drivers/media/platform/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c @@ -233,6 +233,7 @@ err: list_del(buf-list); vb2_buffer_done(buf-vb, VB2_BUF_STATE_QUEUED); } + spin_unlock_irqrestore(common-irqlock, flags); return ret; } -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 12/30] [media] coda: Add runtime pm support
Hi Sylwester, On Fri, Jun 13, 2014 at 06:56:16PM +0200, Sylwester Nawrocki wrote: [...] @@ -3394,10 +3406,29 @@ static void coda_fw_callback(const struct firmware *fw, void *context) memcpy(dev-codebuf.vaddr, fw-data, fw-size); release_firmware(fw); - ret = coda_hw_init(dev); - if (ret) { - v4l2_err(dev-v4l2_dev, HW initialization failed\n); - return; + if (IS_ENABLED(CONFIG_PM_RUNTIME) pdev-dev.pm_domain) { How about using the pm_runtime_enabled() helper ? Also why do you need to be checking dev.pm_domain here and in the resume() callback ? Couldn't it be done unconditionally ? Why the driver needs to care about the PM domain existence ? Thank you for the hint, pm_runtime_enabled() is what I want here. The idea with the pm_domain check was that without an associated pm_domain there is no need to do the hardware initialization over and over again. So if PM_RUNTIME is enabled, but no pm_domain is associated with the device, we call hw_init only once, and not on every runtime_resume. The hardware initialization on coda mostly consists of a 4KiB firmware upload into the code SRAM via an upload register, and a reset of the DSP processor. regards Philipp -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/3] si2168: add one missing parenthesis
Fix following warnings: si2168_cmd_execute() warn: add some parenthesis here? si2168_cmd_execute() warn: maybe use instead of Reported-by: Dan Carpenter dan.carpen...@oracle.com Signed-off-by: Antti Palosaari cr...@iki.fi --- drivers/media/dvb-frontends/si2168.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index 8637d2e..f205736 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -60,7 +60,7 @@ static int si2168_cmd_execute(struct si2168 *s, struct si2168_cmd *cmd) jiffies_to_msecs(jiffies) - (jiffies_to_msecs(timeout) - TIMEOUT)); - if (!(cmd-args[0] 7) 0x01) { + if (!((cmd-args[0] 7) 0x01)) { ret = -ETIMEDOUT; goto err_mutex_unlock; } -- 1.9.3 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/3] si2168: firmware download fix
First 8 bytes belonging to firmware image were hard-coded and uploaded by the driver mistakenly. Introduce new corrected firmware file and remove those 8 bytes from the driver. New firmware image could be extracted from the PCTV 292e driver CD using following command: $ dd if=/TVC 6.4.8/Driver/PCTV Empia/emOEM.sys ibs=1 skip=1089408 count=2728 of=dvb-demod-si2168-02.fw $ md5sum dvb-demod-si2168-02.fw d8da7ff67cd56cd8aa4e101aea45e052 dvb-demod-si2168-02.fw $ sudo cp dvb-demod-si2168-02.fw /lib/firmware/ Signed-off-by: Antti Palosaari cr...@iki.fi --- drivers/media/dvb-frontends/si2168.c | 14 -- drivers/media/dvb-frontends/si2168_priv.h | 2 +- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index f205736..2e3cdcf 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -485,20 +485,6 @@ static int si2168_init(struct dvb_frontend *fe) if (ret) goto err; - cmd.args[0] = 0x05; - cmd.args[1] = 0x00; - cmd.args[2] = 0xaa; - cmd.args[3] = 0x4d; - cmd.args[4] = 0x56; - cmd.args[5] = 0x40; - cmd.args[6] = 0x00; - cmd.args[7] = 0x00; - cmd.wlen = 8; - cmd.rlen = 1; - ret = si2168_cmd_execute(s, cmd); - if (ret) - goto err; - /* cold state - try to download firmware */ dev_info(s-client-dev, %s: found a '%s' in cold state\n, KBUILD_MODNAME, si2168_ops.info.name); diff --git a/drivers/media/dvb-frontends/si2168_priv.h b/drivers/media/dvb-frontends/si2168_priv.h index 2a343e8..53f7f06 100644 --- a/drivers/media/dvb-frontends/si2168_priv.h +++ b/drivers/media/dvb-frontends/si2168_priv.h @@ -22,7 +22,7 @@ #include linux/firmware.h #include linux/i2c-mux.h -#define SI2168_FIRMWARE dvb-demod-si2168-01.fw +#define SI2168_FIRMWARE dvb-demod-si2168-02.fw /* state struct */ struct si2168 { -- 1.9.3 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/3] si2157: add one missing parenthesis
Fix following warnings: si2157_cmd_execute() warn: add some parenthesis here? si2157_cmd_execute() warn: maybe use instead of Reported-by: Dan Carpenter dan.carpen...@oracle.com Signed-off-by: Antti Palosaari cr...@iki.fi --- drivers/media/tuners/si2157.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index 271a752..fa4cc7b 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -57,7 +57,7 @@ static int si2157_cmd_execute(struct si2157 *s, struct si2157_cmd *cmd) jiffies_to_msecs(jiffies) - (jiffies_to_msecs(timeout) - TIMEOUT)); - if (!(buf[0] 7) 0x01) { + if (!((buf[0] 7) 0x01)) { ret = -ETIMEDOUT; goto err_mutex_unlock; } else { -- 1.9.3 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
We offer all purpose loan at 3% interest rate
We offer all purpose loan at 3% interest rate. Contact Us for more details by Email:santanderfinancegr...@gmail.com -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: WG: Patch pctv452e.c: Suppress annoying dmesg-SPAM
Moikka Daniel, On 05/31/2014 12:16 AM, Daniel Mayer wrote: Hi, attached micro-patch removes the text output of an error-message of the PCTV452e-driver. The error messages I2C error: [.] do not help any user of the kernel, so whatever causes the error, it does not hamper the function of my TT-3600 USB receiver. So: Just remove the entries in the dmesg, for it is quite spam-like. Perhaps someone with deeper knowledge could have a look up the background of this message and fix it? Thanks, Daniel (resent as plain-text; sorry) That is not proper fix, it just hides it by removing proper error logging. I debugged real reason earlier: http://permalink.gmane.org/gmane.linux.drivers.video-input-infrastructure/50491 I have got even hardware, but I am totally overloaded so I have to prioritize things. I am happy to see if someone fixes it properly. regards Antti -- http://palosaari.fi/ -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
cron job: media_tree daily build: OK
This message is generated daily by a cron job that builds media_tree for the kernels and architectures in the list below. Results of the daily build of media_tree: date: Sat Jun 14 04:00:46 CEST 2014 git branch: test git hash: f7a27ff1fb77e114d1059a5eb2ed1cffdc508ce8 gcc version:i686-linux-gcc (GCC) 4.8.2 sparse version: v0.5.0-14-gf11dd94 host hardware: x86_64 host os:3.14-5.slh.5-amd64 linux-git-arm-at91: OK linux-git-arm-davinci: OK linux-git-arm-exynos: OK linux-git-arm-mx: OK linux-git-arm-omap: OK linux-git-arm-omap1: OK linux-git-arm-pxa: OK linux-git-blackfin: OK linux-git-i686: OK linux-git-m32r: OK linux-git-mips: OK linux-git-powerpc64: OK linux-git-sh: OK linux-git-x86_64: OK linux-2.6.31.14-i686: OK linux-2.6.32.27-i686: OK linux-2.6.33.7-i686: OK linux-2.6.34.7-i686: OK linux-2.6.35.9-i686: OK linux-2.6.36.4-i686: OK linux-2.6.37.6-i686: OK linux-2.6.38.8-i686: OK linux-2.6.39.4-i686: OK linux-3.0.60-i686: OK linux-3.1.10-i686: OK linux-3.2.37-i686: OK linux-3.3.8-i686: OK linux-3.4.27-i686: OK linux-3.5.7-i686: OK linux-3.6.11-i686: OK linux-3.7.4-i686: OK linux-3.8-i686: OK linux-3.9.2-i686: OK linux-3.10.1-i686: OK linux-3.11.1-i686: OK linux-3.12-i686: OK linux-3.13-i686: OK linux-3.14-i686: OK linux-3.15-rc1-i686: OK linux-2.6.31.14-x86_64: OK linux-2.6.32.27-x86_64: OK linux-2.6.33.7-x86_64: OK linux-2.6.34.7-x86_64: OK linux-2.6.35.9-x86_64: OK linux-2.6.36.4-x86_64: OK linux-2.6.37.6-x86_64: OK linux-2.6.38.8-x86_64: OK linux-2.6.39.4-x86_64: OK linux-3.0.60-x86_64: OK linux-3.1.10-x86_64: OK linux-3.2.37-x86_64: OK linux-3.3.8-x86_64: OK linux-3.4.27-x86_64: OK linux-3.5.7-x86_64: OK linux-3.6.11-x86_64: OK linux-3.7.4-x86_64: OK linux-3.8-x86_64: OK linux-3.9.2-x86_64: OK linux-3.10.1-x86_64: OK linux-3.11.1-x86_64: OK linux-3.12-x86_64: OK linux-3.13-x86_64: OK linux-3.14-x86_64: OK linux-3.15-rc1-x86_64: OK apps: OK spec-git: OK sparse: ERRORS Detailed results are available here: http://www.xs4all.nl/~hverkuil/logs/Saturday.log Full logs are available here: http://www.xs4all.nl/~hverkuil/logs/Saturday.tar.bz2 The Media Infrastructure API from this daily build is here: http://www.xs4all.nl/~hverkuil/spec/media.html -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html