mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 12:17:12 +09:00
Merge commit '72caa4cae073e4ec21db749a613659e10660ecac'
* commit '72caa4cae073e4ec21db749a613659e10660ecac': media: i2c: ov8856: sync driver from kernel4.19 media: i2c: rk628: fix mipi csitx enable sequence Mali: bifrost: Using Upstream For MT Unmapped Area Topdown-Search Revert "PCI: rockchip: dw: remove wakeup if attached device is down" Change-Id: I411ab195f24cb34ad2462ac2370f97749d96bfec
This commit is contained in:
344
drivers/gpu/arm/bifrost/thirdparty/mali_kbase_mmap.c
vendored
344
drivers/gpu/arm/bifrost/thirdparty/mali_kbase_mmap.c
vendored
@@ -20,155 +20,88 @@
|
||||
* kbase_context_get_unmapped_area() interface.
|
||||
*/
|
||||
|
||||
#if (KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE)
|
||||
/**
|
||||
* move_mt_gap() - Search the maple tree for an existing gap of a particular size
|
||||
* immediately before another pre-identified gap.
|
||||
* @gap_start: Pre-identified gap starting address.
|
||||
* @gap_end: Pre-identified gap ending address.
|
||||
* @size: Size of the new gap needed before gap_start.
|
||||
* shader_code_align_and_check() - Align the specified pointer according to shader code
|
||||
* requirement.
|
||||
*
|
||||
* This function will search the calling process' maple tree
|
||||
* for another gap, one that is immediately preceding the pre-identified
|
||||
* gap, for a specific size, and upon success it will decrement gap_end
|
||||
* by the specified size, and replace gap_start with the new gap_start of
|
||||
* the newly identified gap.
|
||||
* @gap_end: Highest possible start address for alignment. The caller must ensure
|
||||
* the input has already been properly aligned with info contained fields.
|
||||
* @info: vm_unmapped_area_info structure passed, containing alignment, length
|
||||
* and limits for the allocation
|
||||
* The function only undertakes the shader code alignment adjustment. It's the caller's
|
||||
* responsibility that the input value provided via gap_end has already been properly aligned
|
||||
* in compliance to the fields specified in the info structure. Irrespective the return result,
|
||||
* the value of the variable pointed by the pointer gap_end may have been decreased in
|
||||
* reaching the required alignment, but will not drop below info->low_limit.
|
||||
*
|
||||
* Return: true if large enough preceding gap is found, false otherwise.
|
||||
* Return: true if gap_end is now aligned correctly, false otherwise
|
||||
*/
|
||||
static bool move_mt_gap(unsigned long *gap_start, unsigned long *gap_end, unsigned long size)
|
||||
static bool shader_code_align_and_check(unsigned long *gap_end, struct vm_unmapped_area_info *info)
|
||||
{
|
||||
unsigned long new_gap_start, new_gap_end;
|
||||
unsigned long align_adjust = (info->align_offset ? info->align_offset : info->length);
|
||||
unsigned long align_floor = info->low_limit + align_adjust;
|
||||
|
||||
MA_STATE(mas, ¤t->mm->mm_mt, 0, 0);
|
||||
/* Check for 4GB address inner high-bit pattern, make adjustment if all zeros */
|
||||
if (0 == (*gap_end & BASE_MEM_MASK_4GB) && *gap_end >= align_floor)
|
||||
(*gap_end) -= align_adjust;
|
||||
if (0 == ((*gap_end + info->length) & BASE_MEM_MASK_4GB) && *gap_end >= align_floor)
|
||||
(*gap_end) -= align_adjust;
|
||||
|
||||
if (*gap_end < size)
|
||||
return false;
|
||||
|
||||
/* Calculate the gap end for the new, resultant gap */
|
||||
new_gap_end = *gap_end - size;
|
||||
|
||||
/* If the new gap_end (i.e. new VA start address) is larger than gap_start, than the
|
||||
* pre-identified gap already has space to shrink to accommodate the decrease in
|
||||
* gap_end.
|
||||
*/
|
||||
if (new_gap_end >= *gap_start) {
|
||||
/* Pre-identified gap already has space - just patch gap_end to new
|
||||
* lower value and exit.
|
||||
*/
|
||||
*gap_end = new_gap_end;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Since the new VA start address (new_gap_end) is below the start of the pre-identified
|
||||
* gap in the maple tree, see if there is a free gap directly before the existing gap, of
|
||||
* the same size as the alignment shift, such that the effective gap found is "extended".
|
||||
* This may be larger than needed but leaves the same distance between gap_end and gap_start
|
||||
* that currently exists.
|
||||
*/
|
||||
new_gap_start = *gap_start - size;
|
||||
if (mas_empty_area_rev(&mas, new_gap_start, *gap_start - 1, size)) {
|
||||
/* There's no gap between the new start address needed and the
|
||||
* current start address - so return false to find a new
|
||||
* gap from the maple tree.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
/* Suitable gap found - replace gap_start and gap_end with new values. gap_start takes the
|
||||
* value of the start of new gap found, which now correctly precedes gap_end, and gap_end
|
||||
* takes on the new aligned value that has now been decremented by the requested size.
|
||||
*/
|
||||
*gap_start = mas.index;
|
||||
*gap_end = new_gap_end;
|
||||
return true;
|
||||
return ((*gap_end & BASE_MEM_MASK_4GB) && ((*gap_end + info->length) & BASE_MEM_MASK_4GB));
|
||||
}
|
||||
|
||||
/**
|
||||
* align_and_check() - Align the specified pointer to the provided alignment and
|
||||
* check that it is still in range. On kernel 6.1 onwards
|
||||
* this function does not require that the initial requested
|
||||
* gap is extended with the maximum size needed to guarantee
|
||||
* an alignment.
|
||||
* @gap_end: Highest possible start address for allocation (end of gap in
|
||||
* address space)
|
||||
* @gap_start: Start address of current memory area / gap in address space
|
||||
* @info: vm_unmapped_area_info structure passed to caller, containing
|
||||
* alignment, length and limits for the allocation
|
||||
* @is_shader_code: True if the allocation is for shader code (which has
|
||||
* additional alignment requirements)
|
||||
* @is_same_4gb_page: True if the allocation needs to reside completely within
|
||||
* a 4GB chunk
|
||||
* align_4gb_no_straddle() - Align the specified pointer not to straddle over a 4_GB boundary.
|
||||
*
|
||||
* Return: true if gap_end is now aligned correctly and is still in range,
|
||||
* false otherwise
|
||||
* @gap_end: Highest possible start address for alignment. The caller must ensure
|
||||
* the input has already been properly aligned with info contained fields.
|
||||
* @info: vm_unmapped_area_info structure passed, containing alignment, length
|
||||
* and limits for the allocation
|
||||
*
|
||||
* The function only undertakes the 4GB boundary alignment adjustment. It's the caller's
|
||||
* responsibility that the input value provided via gap_end has already been properly aligned
|
||||
* in compliance to the fields specified in the info structure.
|
||||
*
|
||||
* Return: true is always expected and the gap_end is aligned correctly, false can only
|
||||
* be possible when the code has been wrongly modified.
|
||||
*/
|
||||
static bool align_and_check(unsigned long *gap_end, unsigned long gap_start,
|
||||
struct vm_unmapped_area_info *info, bool is_shader_code,
|
||||
bool is_same_4gb_page)
|
||||
static bool align_4gb_no_straddle(unsigned long *gap_end, struct vm_unmapped_area_info *info)
|
||||
{
|
||||
unsigned long alignment_shift;
|
||||
unsigned long start = *gap_end;
|
||||
unsigned long end = *gap_end + info->length;
|
||||
unsigned long mask = ~((unsigned long)U32_MAX);
|
||||
|
||||
/* Compute highest gap address at the desired alignment */
|
||||
*gap_end -= info->length;
|
||||
alignment_shift = (*gap_end - info->align_offset) & info->align_mask;
|
||||
/* Check if 4GB boundary is straddled */
|
||||
if ((start & mask) != ((end - 1) & mask)) {
|
||||
unsigned long offset = end - (end & mask);
|
||||
/* This is to ensure that alignment doesn't get
|
||||
* disturbed in an attempt to prevent straddling at
|
||||
* 4GB boundary. The GPU VA is aligned to 2MB when the
|
||||
* allocation size is > 2MB and there is enough CPU &
|
||||
* GPU virtual space.
|
||||
*/
|
||||
unsigned long rounded_offset = ALIGN(offset, info->align_mask + 1);
|
||||
|
||||
/* Align desired start VA (gap_end) by calculated alignment shift amount */
|
||||
if (!move_mt_gap(&gap_start, gap_end, alignment_shift))
|
||||
return false;
|
||||
/* Alignment is done so far - check for further alignment requirements */
|
||||
start -= rounded_offset;
|
||||
end -= rounded_offset;
|
||||
|
||||
if (is_shader_code) {
|
||||
/* Shader code allocations must not start or end on a 4GB boundary */
|
||||
alignment_shift = info->align_offset ? info->align_offset : info->length;
|
||||
if (0 == (*gap_end & BASE_MEM_MASK_4GB)) {
|
||||
if (!move_mt_gap(&gap_start, gap_end, alignment_shift))
|
||||
return false;
|
||||
}
|
||||
if (0 == ((*gap_end + info->length) & BASE_MEM_MASK_4GB)) {
|
||||
if (!move_mt_gap(&gap_start, gap_end, alignment_shift))
|
||||
return false;
|
||||
}
|
||||
/* Patch gap_end to use new starting address for VA region */
|
||||
*gap_end = start;
|
||||
|
||||
if (!(*gap_end & BASE_MEM_MASK_4GB) ||
|
||||
!((*gap_end + info->length) & BASE_MEM_MASK_4GB))
|
||||
/* The preceding 4GB boundary shall not get straddled,
|
||||
* even after accounting for the alignment, as the
|
||||
* size of allocation is limited to 4GB and the initial
|
||||
* start location was already aligned.
|
||||
*/
|
||||
if (WARN_ONCE((start & mask) != ((end - 1) & mask),
|
||||
"Alignment unexpected straddles over 4GB boundary!"))
|
||||
return false;
|
||||
} else if (is_same_4gb_page) {
|
||||
unsigned long start = *gap_end;
|
||||
unsigned long end = *gap_end + info->length;
|
||||
unsigned long mask = ~((unsigned long)U32_MAX);
|
||||
|
||||
/* Check if 4GB boundary is straddled */
|
||||
if ((start & mask) != ((end - 1) & mask)) {
|
||||
unsigned long offset = end - (end & mask);
|
||||
/* This is to ensure that alignment doesn't get
|
||||
* disturbed in an attempt to prevent straddling at
|
||||
* 4GB boundary. The GPU VA is aligned to 2MB when the
|
||||
* allocation size is > 2MB and there is enough CPU &
|
||||
* GPU virtual space.
|
||||
*/
|
||||
unsigned long rounded_offset = ALIGN(offset, info->align_mask + 1);
|
||||
|
||||
if (!move_mt_gap(&gap_start, gap_end, rounded_offset))
|
||||
return false;
|
||||
/* Re-calculate start and end values */
|
||||
start = *gap_end;
|
||||
end = *gap_end + info->length;
|
||||
|
||||
/* The preceding 4GB boundary shall not get straddled,
|
||||
* even after accounting for the alignment, as the
|
||||
* size of allocation is limited to 4GB and the initial
|
||||
* start location was already aligned.
|
||||
*/
|
||||
WARN_ON((start & mask) != ((end - 1) & mask));
|
||||
}
|
||||
}
|
||||
|
||||
if ((*gap_end < info->low_limit) || (*gap_end < gap_start))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
|
||||
#if (KERNEL_VERSION(6, 1, 0) > LINUX_VERSION_CODE) || !defined(__ANDROID_COMMON_KERNEL__)
|
||||
/**
|
||||
* align_and_check() - Align the specified pointer to the provided alignment and
|
||||
* check that it is still in range. For Kernel versions below
|
||||
@@ -196,45 +129,11 @@ static bool align_and_check(unsigned long *gap_end, unsigned long gap_start,
|
||||
*gap_end -= (*gap_end - info->align_offset) & info->align_mask;
|
||||
|
||||
if (is_shader_code) {
|
||||
/* Check for 4GB boundary */
|
||||
if (0 == (*gap_end & BASE_MEM_MASK_4GB))
|
||||
(*gap_end) -= (info->align_offset ? info->align_offset : info->length);
|
||||
if (0 == ((*gap_end + info->length) & BASE_MEM_MASK_4GB))
|
||||
(*gap_end) -= (info->align_offset ? info->align_offset : info->length);
|
||||
|
||||
if (!(*gap_end & BASE_MEM_MASK_4GB) ||
|
||||
!((*gap_end + info->length) & BASE_MEM_MASK_4GB))
|
||||
if (!shader_code_align_and_check(gap_end, info))
|
||||
return false;
|
||||
} else if (is_same_4gb_page)
|
||||
if (!align_4gb_no_straddle(gap_end, info))
|
||||
return false;
|
||||
} else if (is_same_4gb_page) {
|
||||
unsigned long start = *gap_end;
|
||||
unsigned long end = *gap_end + info->length;
|
||||
unsigned long mask = ~((unsigned long)U32_MAX);
|
||||
|
||||
/* Check if 4GB boundary is straddled */
|
||||
if ((start & mask) != ((end - 1) & mask)) {
|
||||
unsigned long offset = end - (end & mask);
|
||||
/* This is to ensure that alignment doesn't get
|
||||
* disturbed in an attempt to prevent straddling at
|
||||
* 4GB boundary. The GPU VA is aligned to 2MB when the
|
||||
* allocation size is > 2MB and there is enough CPU &
|
||||
* GPU virtual space.
|
||||
*/
|
||||
unsigned long rounded_offset = ALIGN(offset, info->align_mask + 1);
|
||||
|
||||
start -= rounded_offset;
|
||||
end -= rounded_offset;
|
||||
|
||||
/* Patch gap_end to use new starting address for VA region */
|
||||
*gap_end = start;
|
||||
|
||||
/* The preceding 4GB boundary shall not get straddled,
|
||||
* even after accounting for the alignment, as the
|
||||
* size of allocation is limited to 4GB and the initial
|
||||
* start location was already aligned.
|
||||
*/
|
||||
WARN_ON((start & mask) != ((end - 1) & mask));
|
||||
}
|
||||
}
|
||||
|
||||
if ((*gap_end < info->low_limit) || (*gap_end < gap_start))
|
||||
return false;
|
||||
@@ -370,33 +269,124 @@ check_current:
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
unsigned long high_limit, gap_start, gap_end;
|
||||
#else /* KERNEL_VERSION(6, 1, 0) > LINUX_VERSION_CODE */
|
||||
#ifdef __ANDROID_COMMON_KERNEL__
|
||||
struct vm_unmapped_area_info tmp_info = *info;
|
||||
unsigned long length;
|
||||
|
||||
tmp_info.flags |= VM_UNMAPPED_AREA_TOPDOWN;
|
||||
if (!(is_shader_code || is_same_4gb_page))
|
||||
return vm_unmapped_area(&tmp_info);
|
||||
|
||||
length = info->length + info->align_mask;
|
||||
|
||||
/* Due to additional alignment requirement, shader_code or same_4gb_page
|
||||
* needs iterations for alignment search and confirmation check.
|
||||
*/
|
||||
while (true) {
|
||||
unsigned long saved_high_lmt = tmp_info.high_limit;
|
||||
unsigned long gap_end, start, rev_high_limit;
|
||||
|
||||
gap_end = vm_unmapped_area(&tmp_info);
|
||||
if (IS_ERR_VALUE(gap_end))
|
||||
return gap_end;
|
||||
|
||||
start = gap_end;
|
||||
if (is_shader_code) {
|
||||
bool shader_code_aligned;
|
||||
unsigned long align_cmp_ref;
|
||||
|
||||
while (true) {
|
||||
/* Save the start value for progress check. the loop needs
|
||||
* to end if the alignment can't progress any further.
|
||||
* In summary, the loop ends condition here is either:
|
||||
* 1. shader_code_aligned is true; or
|
||||
* 2. align_cmp_ref == gap_end.
|
||||
*/
|
||||
align_cmp_ref = gap_end;
|
||||
|
||||
shader_code_aligned =
|
||||
shader_code_align_and_check(&gap_end, &tmp_info);
|
||||
if (shader_code_aligned || (align_cmp_ref == gap_end))
|
||||
break;
|
||||
}
|
||||
|
||||
if (shader_code_aligned) {
|
||||
if (start == gap_end)
|
||||
return gap_end;
|
||||
|
||||
rev_high_limit = gap_end + length;
|
||||
} else
|
||||
break;
|
||||
} else {
|
||||
/* must be same_4gb_page case */
|
||||
if (likely(align_4gb_no_straddle(&gap_end, &tmp_info))) {
|
||||
if (start == gap_end)
|
||||
return gap_end;
|
||||
|
||||
rev_high_limit = gap_end + length;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
if (rev_high_limit < info->low_limit)
|
||||
break;
|
||||
|
||||
if (WARN_ONCE(rev_high_limit >= saved_high_lmt,
|
||||
"Unexpected recurring high_limit in search, %lx => %lx\n"
|
||||
"\tinfo-input: limit=[%lx, %lx], mask=%lx, len=%lx\n",
|
||||
saved_high_lmt, rev_high_limit, info->low_limit, info->high_limit,
|
||||
info->align_mask, info->length))
|
||||
rev_high_limit = saved_high_lmt -
|
||||
(info->align_offset ? info->align_offset : info->length);
|
||||
|
||||
/* Repeat the search with a decreasing rev_high_limit */
|
||||
tmp_info.high_limit = rev_high_limit;
|
||||
}
|
||||
#else /* __ANDROID_COMMON_KERNEL__ */
|
||||
unsigned long length, high_limit;
|
||||
|
||||
MA_STATE(mas, ¤t->mm->mm_mt, 0, 0);
|
||||
|
||||
/*
|
||||
* Adjust search limits by the desired length.
|
||||
* See implementation comment at top of unmapped_area().
|
||||
*/
|
||||
gap_end = info->high_limit;
|
||||
if (gap_end < info->length)
|
||||
/* Adjust search length to account for worst case alignment overhead */
|
||||
length = info->length + info->align_mask;
|
||||
if (length < info->length)
|
||||
return -ENOMEM;
|
||||
high_limit = gap_end - info->length;
|
||||
|
||||
if (info->low_limit > high_limit)
|
||||
high_limit = info->high_limit;
|
||||
if ((high_limit - info->low_limit) < length)
|
||||
return -ENOMEM;
|
||||
|
||||
while (true) {
|
||||
if (mas_empty_area_rev(&mas, info->low_limit, info->high_limit - 1, info->length))
|
||||
unsigned long gap_start, gap_end;
|
||||
unsigned long saved_high_lmt = high_limit;
|
||||
|
||||
if (mas_empty_area_rev(&mas, info->low_limit, high_limit - 1, length))
|
||||
return -ENOMEM;
|
||||
|
||||
gap_end = mas.last + 1;
|
||||
gap_start = mas.index;
|
||||
|
||||
if (align_and_check(&gap_end, gap_start, info, is_shader_code, is_same_4gb_page))
|
||||
return gap_end;
|
||||
|
||||
if (gap_end < info->low_limit)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Adjust next search high limit */
|
||||
high_limit = gap_end + length;
|
||||
|
||||
if (WARN_ONCE(high_limit >= saved_high_lmt,
|
||||
"Unexpected recurring high_limit in search, %lx => %lx\n"
|
||||
"\tinfo-input: limit=[%lx, %lx], mask=%lx, len=%lx\n",
|
||||
saved_high_lmt, high_limit, info->low_limit, info->high_limit,
|
||||
info->align_mask, info->length))
|
||||
high_limit = saved_high_lmt -
|
||||
(info->align_offset ? info->align_offset : info->length);
|
||||
mas_reset(&mas);
|
||||
}
|
||||
#endif
|
||||
#endif /* __ANDROID_COMMON_KERNEL__ */
|
||||
#endif /* KERNEL_VERSION(6, 1, 0) > LINUX_VERSION_CODE */
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -755,7 +755,17 @@ static void rk628_csi_soft_reset(struct v4l2_subdev *sd)
|
||||
static void enable_csitx(struct v4l2_subdev *sd)
|
||||
{
|
||||
struct rk628_csi *csi = to_csi(sd);
|
||||
u32 mask = SW_OUTPUT_MODE_MASK;
|
||||
u32 val = SW_OUTPUT_MODE(OUTPUT_MODE_CSI);
|
||||
|
||||
if (csi->rk628->version == RK628F_VERSION) {
|
||||
mask = SW_OUTPUT_COMBTX_MODE_MASK;
|
||||
val = SW_OUTPUT_COMBTX_MODE(OUTPUT_MODE_CSI - 1);
|
||||
rk628_i2c_update_bits(csi->rk628, GRF_SYSTEM_CON3,
|
||||
GRF_AS_DSIPHY_MASK,
|
||||
GRF_AS_DSIPHY(0));
|
||||
}
|
||||
rk628_i2c_update_bits(csi->rk628, GRF_SYSTEM_CON0, mask, val);
|
||||
//enable dphy1 and split mode
|
||||
rk628_i2c_update_bits(csi->rk628, GRF_SYSTEM_CON3, GRF_DPHY_CH1_EN_MASK,
|
||||
csi->rk628->dual_mipi ? GRF_DPHY_CH1_EN(1) : 0);
|
||||
@@ -912,6 +922,7 @@ static void rk628_csi_disable_stream(struct v4l2_subdev *sd)
|
||||
csi->continues_clk ? CONT_MODE_CLK_CLR(1) : CONT_MODE_CLK_CLR(0));
|
||||
rk628_i2c_write(csi->rk628, CSITX1_CONFIG_DONE, CONFIG_DONE_IMD);
|
||||
}
|
||||
rk628_csi_soft_reset(sd);
|
||||
mipi_dphy_power_off(csi);
|
||||
csi->txphy_pwron = false;
|
||||
csi->is_streaming = false;
|
||||
@@ -935,14 +946,17 @@ static void enable_stream(struct v4l2_subdev *sd, bool en)
|
||||
return;
|
||||
}
|
||||
|
||||
if (csi->plat_data->tx_mode == DSI_MODE) {
|
||||
if (csi->plat_data->tx_mode == DSI_MODE)
|
||||
enable_dsitx(sd);
|
||||
} else {
|
||||
else
|
||||
enable_csitx(sd);
|
||||
/* csitx int en */
|
||||
|
||||
rk628_hdmirx_vid_enable(sd, true);
|
||||
if (csi->plat_data->tx_mode == CSI_MODE) {
|
||||
msleep(20);
|
||||
rk628_mipi_txdata_reset(sd);
|
||||
rk628_csi_enable_csi_interrupts(sd, true);
|
||||
}
|
||||
rk628_hdmirx_vid_enable(sd, true);
|
||||
|
||||
rk628_i2c_update_bits(csi->rk628, HDMI_RX_PDEC_CTRL,
|
||||
GCPFORCE_CLRAVMUTE_MASK, GCPFORCE_CLRAVMUTE(1));
|
||||
@@ -1681,6 +1695,7 @@ static void rk628_csi_error_process(struct v4l2_subdev *sd)
|
||||
#if IS_REACHABLE(CONFIG_VIDEO_ROCKCHIP_CIF)
|
||||
rk628_csi_reset_rkcif(sd);
|
||||
#endif
|
||||
|
||||
rk628_i2c_update_bits(csi->rk628, CSITX_CSITX_EN, CSITX_EN_MASK, CSITX_EN(1));
|
||||
rk628_i2c_write(csi->rk628, CSITX_CONFIG_DONE, CONFIG_DONE_IMD);
|
||||
if (csi->rk628->version >= RK628F_VERSION) {
|
||||
@@ -1710,8 +1725,10 @@ static void rk628_csi_error_process(struct v4l2_subdev *sd)
|
||||
CSITX1_CONFIG_DONE, CONFIG_DONE_IMD);
|
||||
}
|
||||
}
|
||||
rk628_csi_enable_csi_interrupts(sd, true);
|
||||
rk628_hdmirx_vid_enable(sd, true);
|
||||
msleep(20);
|
||||
rk628_mipi_txdata_reset(sd);
|
||||
rk628_csi_enable_csi_interrupts(sd, true);
|
||||
v4l2_dbg(1, debug, sd, "%s, do reset successful\n", __func__);
|
||||
} else {
|
||||
v4l2_info(sd,
|
||||
@@ -2465,12 +2482,16 @@ static void rk628_csi_reset_streaming(struct v4l2_subdev *sd, int on)
|
||||
DPHY_EN_MASK | CSITX_EN_MASK, DPHY_EN(1) | CSITX_EN(1));
|
||||
rk628_i2c_write(csi->rk628, CSITX1_CONFIG_DONE, CONFIG_DONE_IMD);
|
||||
}
|
||||
rk628_csi_enable_csi_interrupts(sd, true);
|
||||
csi->is_streaming = true;
|
||||
} else {
|
||||
enable_dsitx(sd);
|
||||
}
|
||||
rk628_hdmirx_vid_enable(sd, true);
|
||||
if (csi->plat_data->tx_mode == CSI_MODE) {
|
||||
msleep(20);
|
||||
rk628_mipi_txdata_reset(sd);
|
||||
rk628_csi_enable_csi_interrupts(sd, true);
|
||||
csi->is_streaming = true;
|
||||
}
|
||||
} else {
|
||||
rk628_hdmirx_vid_enable(sd, false);
|
||||
if (csi->plat_data->tx_mode == CSI_MODE) {
|
||||
@@ -2644,10 +2665,12 @@ static int mipi_dphy_power_on(struct rk628_csi *csi)
|
||||
bus_width |= COMBTXPHY_MODULEB_EN;
|
||||
v4l2_dbg(1, debug, sd, "%s mipi bitrate:%llu mbps\n", __func__,
|
||||
csi->lane_mbps);
|
||||
rk628_mipi_dphy_reset_assert(csi->rk628);
|
||||
rk628_mipi_dphy_reset_deassert(csi->rk628);
|
||||
|
||||
rk628_txphy_set_bus_width(csi->rk628, bus_width);
|
||||
rk628_txphy_set_mode(csi->rk628, PHY_MODE_VIDEO_MIPI);
|
||||
|
||||
rk628_mipi_dphy_reset_assert(csi->rk628);
|
||||
rk628_mipi_dphy_init_hsfreqrange(csi->rk628, csi->lane_mbps, 0);
|
||||
if (csi->rk628->version >= RK628F_VERSION)
|
||||
rk628_mipi_dphy_init_hsfreqrange(csi->rk628, csi->lane_mbps, 1);
|
||||
@@ -2664,25 +2687,23 @@ static int mipi_dphy_power_on(struct rk628_csi *csi)
|
||||
if (csi->rk628->version >= RK628F_VERSION)
|
||||
rk628_mipi_dphy_init_hsmanual(csi->rk628, false, 1);
|
||||
}
|
||||
rk628_mipi_dphy_reset_deassert(csi->rk628);
|
||||
usleep_range(1500, 2000);
|
||||
rk628_txphy_power_on(csi->rk628);
|
||||
|
||||
usleep_range(1500, 2000);
|
||||
mask = DPHY_PLL_LOCK;
|
||||
rk628_i2c_read(csi->rk628, CSITX_CSITX_STATUS1, &val);
|
||||
if ((val & mask) != mask) {
|
||||
dev_err(csi->dev, "PHY is not locked\n");
|
||||
return -1;
|
||||
}
|
||||
ret = regmap_read_poll_timeout(csi->rk628->regmap[RK628_DEV_CSI],
|
||||
CSITX_CSITX_STATUS1,
|
||||
val, val & DPHY_PLL_LOCK,
|
||||
0, 1000);
|
||||
if (ret < 0)
|
||||
dev_err(csi->rk628->dev, "csi0 phy is not locked\n");
|
||||
if (csi->rk628->version >= RK628F_VERSION) {
|
||||
rk628_i2c_read(csi->rk628, CSITX1_CSITX_STATUS1, &val);
|
||||
if ((val & mask) != mask) {
|
||||
dev_err(csi->dev, "PHY1 is not locked\n");
|
||||
return -1;
|
||||
}
|
||||
ret = regmap_read_poll_timeout(csi->rk628->regmap[RK628_DEV_CSI1],
|
||||
CSITX1_CSITX_STATUS1,
|
||||
val, val & DPHY_PLL_LOCK,
|
||||
0, 1000);
|
||||
if (ret < 0)
|
||||
dev_err(csi->rk628->dev, "csi1 phy is not locked\n");
|
||||
}
|
||||
udelay(10);
|
||||
|
||||
mask = STOPSTATE_CLK | STOPSTATE_LANE0;
|
||||
ret = regmap_read_poll_timeout(csi->rk628->regmap[RK628_DEV_CSI],
|
||||
|
||||
@@ -130,6 +130,20 @@ static inline void mipi_dphy_enablelane_deassert(struct rk628 *rk628, uint8_t mi
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void mipi_dphy_enableclk_assert(struct rk628 *rk628, uint8_t mipi_id)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, mipi_id ? CSITX1_DPHY_CTRL : CSITX_DPHY_CTRL,
|
||||
DPHY_ENABLECLK, DPHY_ENABLECLK);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void mipi_dphy_enableclk_deassert(struct rk628 *rk628, uint8_t mipi_id)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, mipi_id ? CSITX1_DPHY_CTRL : CSITX_DPHY_CTRL,
|
||||
DPHY_ENABLECLK, 0);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void mipi_dphy_shutdownz_assert(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON, CSI_PHYSHUTDOWNZ, 0);
|
||||
@@ -227,9 +241,9 @@ int rk628_mipi_dphy_reset_assert(struct rk628 *rk628)
|
||||
rk628_i2c_write(rk628, CSITX_SYS_CTRL0_IMD, 0x1);
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
rk628_i2c_write(rk628, CSITX1_SYS_CTRL0_IMD, 0x1);
|
||||
mipi_dphy_enablelane_deassert(rk628, 0);
|
||||
mipi_dphy_enableclk_deassert(rk628, 0);
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
mipi_dphy_enablelane_deassert(rk628, 1);
|
||||
mipi_dphy_enableclk_deassert(rk628, 1);
|
||||
mipi_dphy_shutdownz_assert(rk628);
|
||||
mipi_dphy_rstz_assert(rk628);
|
||||
rk628_testif_testclr_assert(rk628, 0);
|
||||
@@ -248,9 +262,9 @@ int rk628_mipi_dphy_reset_assert(struct rk628 *rk628)
|
||||
rk628_testif_testclr_deassert(rk628, 0);
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
rk628_testif_testclr_deassert(rk628, 1);
|
||||
mipi_dphy_enablelane_assert(rk628, 0);
|
||||
mipi_dphy_enableclk_assert(rk628, 0);
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
mipi_dphy_enablelane_assert(rk628, 1);
|
||||
mipi_dphy_enableclk_assert(rk628, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1677,8 +1677,7 @@ static int rk_pcie_really_probe(void *p)
|
||||
dw_pcie_dbi_ro_wr_dis(pci);
|
||||
|
||||
/* 7. framework misc settings */
|
||||
if (rk_pcie->skip_scan_in_resume)
|
||||
device_init_wakeup(dev, true);
|
||||
device_init_wakeup(dev, true);
|
||||
device_enable_async_suspend(dev); /* Enable async system PM for multiports SoC */
|
||||
rk_pcie->finish_probe = true;
|
||||
|
||||
@@ -1914,10 +1913,8 @@ static int __maybe_unused rockchip_dw_pcie_suspend(struct device *dev)
|
||||
*/
|
||||
if (rk_pcie->skip_scan_in_resume) {
|
||||
rfkill_get_wifi_power_state(&power);
|
||||
if (!power) {
|
||||
device_init_wakeup(dev, false);
|
||||
if (!power)
|
||||
goto no_l2;
|
||||
}
|
||||
}
|
||||
|
||||
/* 2. Broadcast PME_Turn_Off Message */
|
||||
@@ -2005,8 +2002,6 @@ static int __maybe_unused rockchip_dw_pcie_resume(struct device *dev)
|
||||
|
||||
dw_pcie_dbi_ro_wr_dis(pci);
|
||||
rk_pcie->in_suspend = false;
|
||||
if (rk_pcie->skip_scan_in_resume)
|
||||
device_init_wakeup(dev, true);
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user