fix(camera,sms,dwm): fix CAMSS AXI frame-boundary stop, SMS draft button label, and post-reboot softkey responsiveness
This commit is contained in:
@@ -81,7 +81,7 @@ static const struct gc2395_reg gc2395_init_regs[] = {
|
||||
{ 0xf4, 0x03 }, { 0xf7, 0x01 }, { 0xf8, 0x28 }, { 0xf9, 0x02 },
|
||||
{ 0xfa, 0x08 }, { 0xfc, 0x8e }, { 0xe7, 0xcc }, { 0x88, 0x03 },
|
||||
{ 0x03, 0x04 }, { 0x04, 0x80 }, { 0x05, 0x02 }, { 0x06, 0x86 },
|
||||
{ 0x07, 0x00 }, { 0x08, 0x20 }, { 0x09, 0x00 }, { 0x0a, 0x04 },
|
||||
{ 0x07, 0x02 }, { 0x08, 0x00 }, { 0x09, 0x00 }, { 0x0a, 0x04 },
|
||||
{ 0x0b, 0x00 }, { 0x0c, 0x02 }, { 0x17, 0xd7 }, { 0x18, 0x02 },
|
||||
{ 0x19, 0x17 }, { 0x1c, 0x18 }, { 0x20, 0x73 }, { 0x22, 0xa2 },
|
||||
{ 0x21, 0x38 }, { 0x29, 0x20 }, { 0x2f, 0x14 }, { 0x3f, 0x40 },
|
||||
@@ -314,14 +314,35 @@ static void gc2395_write_reg(struct msm8905_cam_dev *cam, u8 reg, u8 val)
|
||||
cam_i2c_stop(cam);
|
||||
}
|
||||
|
||||
static void msm8905_cam_enable_clocks(struct msm8905_cam_dev *cam)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (cam_r32(cam->gcc_base, 0x58034U) & 1U) {
|
||||
cam_w32(cam->gcc_base, 0x58034U, cam_r32(cam->gcc_base, 0x58034U) & ~1U);
|
||||
usleep_range(1000, 2000);
|
||||
}
|
||||
if ((cam_r32(cam->gcc_base, 0x4500cU) & 0x3202U) != 0x3202U) {
|
||||
cam_w32(cam->gcc_base, 0x4500cU, cam_r32(cam->gcc_base, 0x4500cU) | 0x3202U);
|
||||
usleep_range(1000, 2000);
|
||||
}
|
||||
for (i = 0; i < ARRAY_SIZE(camss_cbcr_offsets); i++) {
|
||||
if ((cam_r32(cam->gcc_base, camss_cbcr_offsets[i]) & 1U) == 0U ||
|
||||
(cam_r32(cam->gcc_base, camss_cbcr_offsets[i]) & 0x80000000U) != 0U)
|
||||
cam_enable_cbcr(cam, camss_cbcr_offsets[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static int msm8905_cam_hw_init(struct msm8905_cam_dev *cam)
|
||||
{
|
||||
size_t i;
|
||||
u16 chip_id;
|
||||
u32 r;
|
||||
|
||||
if (cam->hw_initialized)
|
||||
if (cam->hw_initialized) {
|
||||
msm8905_cam_enable_clocks(cam);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 1. Ensure PM8909 LDO6 (1.8V) and LDO17 (2.85V) are enabled */
|
||||
if (cam->usid1_regmap) {
|
||||
@@ -498,11 +519,16 @@ static int msm8905_cam_capture_rgb(struct msm8905_cam_dev *cam, u8 *dst_rgb)
|
||||
ret = msm8905_cam_hw_init(cam);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
msm8905_cam_enable_clocks(cam);
|
||||
}
|
||||
|
||||
/* Ensure GC2395 stream and VFE0 WM0/RDI0 are idle before resetting ISPIF */
|
||||
/* Ensure GC2395 stream and ISPIF/VFE0 are idle before arming next frame */
|
||||
cam_w32(cam->camss_base, ISPIF_BASE + 0x248U, 0xaaaaaaaaU);
|
||||
wmb();
|
||||
gc2395_write_reg(cam, 0xfeU, 0x00U);
|
||||
gc2395_write_reg(cam, 0xedU, 0x00U);
|
||||
usleep_range(600, 900);
|
||||
cam_w32(cam->camss_base, VFE0_BASE + 0x04cU, 0x00000000U);
|
||||
cam_w32(cam->camss_base, VFE0_BASE + 0x6fcU, 0x00000000U);
|
||||
wmb();
|
||||
@@ -538,7 +564,7 @@ static int msm8905_cam_capture_rgb(struct msm8905_cam_dev *cam, u8 *dst_rgb)
|
||||
cam_w32(cam->camss_base, VFE0_BASE + 0x018U, 0x00000001U);
|
||||
cam_w32(cam->camss_base, VFE0_BASE + 0x260U, 0x00000002U);
|
||||
|
||||
/* Enable ISPIF RDI0 CID0 on frame boundary and start GC2395 MIPI stream */
|
||||
/* Enable ISPIF RDI0 on frame boundary and start GC2395 MIPI stream */
|
||||
cam_w32(cam->camss_base, ISPIF_BASE + 0x248U, 0xfffffdffU);
|
||||
wmb();
|
||||
|
||||
@@ -546,30 +572,40 @@ static int msm8905_cam_capture_rgb(struct msm8905_cam_dev *cam, u8 *dst_rgb)
|
||||
gc2395_write_reg(cam, 0xedU, 0x90U);
|
||||
gc2395_write_reg(cam, 0xfeU, 0x00U);
|
||||
|
||||
/* Wait for WM0 PING_PONG_IRQ (bit 6 = 0x40) */
|
||||
/*
|
||||
* Poll for WM0 PING_PONG_IRQ (bit 6 = 0x40) with sub-millisecond sleep so we
|
||||
* catch EOF right inside the 14 ms vertical blanking window before Frame 2.
|
||||
*/
|
||||
irq0 = 0;
|
||||
for (poll_cnt = 0; poll_cnt < 150; poll_cnt++) {
|
||||
for (poll_cnt = 0; poll_cnt < 400; poll_cnt++) {
|
||||
irq0 = cam_r32(cam->camss_base, VFE0_BASE + 0x02cU);
|
||||
if (irq0 & 0x00000040U)
|
||||
break;
|
||||
usleep_range(2000, 3000);
|
||||
usleep_range(400, 600);
|
||||
}
|
||||
|
||||
/* Stop GC2395 stream, WM0, and RDI0 cleanly */
|
||||
/*
|
||||
* 1. Gate ISPIF at frame boundary FIRST so VFE0 never receives a partial frame.
|
||||
* 2. Stop GC2395 MIPI stream during VBLANK (LP-11 state).
|
||||
* 3. Wait for VFE0 WM0 / VBIF AXI write bursts to drain completely before
|
||||
* clearing WM0_CFG and RDI0_CFG.
|
||||
*/
|
||||
cam_w32(cam->camss_base, ISPIF_BASE + 0x248U, 0xaaaaaaaaU);
|
||||
wmb();
|
||||
gc2395_write_reg(cam, 0xfeU, 0x00U);
|
||||
gc2395_write_reg(cam, 0xedU, 0x00U);
|
||||
usleep_range(800, 1200);
|
||||
cam_w32(cam->camss_base, VFE0_BASE + 0x04cU, 0x00000000U);
|
||||
cam_w32(cam->camss_base, VFE0_BASE + 0x6fcU, 0x00000000U);
|
||||
cam_w32(cam->camss_base, VFE0_BASE + 0x024U, 0xffffffffU);
|
||||
cam_w32(cam->camss_base, VFE0_BASE + 0x028U, 0xffffffffU);
|
||||
cam_w32(cam->camss_base, VFE0_BASE + 0x018U, 0x00000001U);
|
||||
cam_w32(cam->camss_base, ISPIF_BASE + 0x008U, 0x00001ff9U);
|
||||
usleep_range(500, 1000);
|
||||
cam_w32(cam->camss_base, ISPIF_BASE + 0x008U, 0x00000000U);
|
||||
wmb();
|
||||
|
||||
if (!(irq0 & 0x00000040U))
|
||||
if (!(irq0 & 0x00000040U)) {
|
||||
cam->hw_initialized = false;
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
msm8905_cam_demosaic(cam->raw_dma_buf, dst_rgb);
|
||||
cam->sequence++;
|
||||
|
||||
Reference in New Issue
Block a user