mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-11 13:27:06 +09:00
Merge commit '15f661b3f5b9c4ed2a24ea4e9656394ed4c399f4'
* commit '15f661b3f5b9c4ed2a24ea4e9656394ed4c399f4': (21 commits) media: rockchip: hdmirx: corrected color range/space judgment. drm/rockchip: dw-dp: config color range for different color format media: i2c: rk628: fix set output color space media: i2c: rk628: fix bug of clear hdmirx ints media: i2c: dw9714: fix motor is closed after execute v4l2-ctl media: i2c: lens: fix motor is closed after execute v4l2-ctl media: i2c: cn3927v: fix motor is closed after execute v4l2-ctl usb: dwc3: gadget: Fix stop active transfer usb: dwc3: gadget: Move all started reqs to cancelled list on dequeue UPSTREAM: usb: dwc3: gadget: Handle EP0 request dequeuing properly UPSTREAM: usb: dwc3: gadget: Refactor EP0 forced stall/restart into a separate API usb: typec: husb311: fix non-standard cable that cc double pull-up drm/rockchip: vop2: Update post csc info when post csc prop changed scsi: ufs: rockchip: Remove ufshcd_*_suspend/resume call arm64: dts: rockchip: rk3576-evb: Enable hdmi uboot logo arm64: dts: rockchip: rk3576-tablet: modify dsi panel and tp config input: touchscreen: chipone_tddi: use panel notifier to fix resume/suspend timing Revert "input: touchscreen: chipone_9551r add early_suspend" drm/panel: panel-simple: add panel notifier for tp resume/suspend drm/rockchip: panel-notifier: add panel notifier for panel-related device ... Change-Id: Id98e1ab25f94aaee4201704e4382b19ff7a54e27
This commit is contained in:
@@ -504,7 +504,7 @@
|
||||
};
|
||||
|
||||
&route_hdmi {
|
||||
status = "disabled";
|
||||
status = "okay";
|
||||
connect = <&vp0_out_hdmi>;
|
||||
};
|
||||
|
||||
|
||||
@@ -408,7 +408,7 @@
|
||||
};
|
||||
|
||||
&route_hdmi {
|
||||
status = "disabled";
|
||||
status = "okay";
|
||||
connect = <&vp0_out_hdmi>;
|
||||
};
|
||||
|
||||
|
||||
@@ -306,8 +306,8 @@
|
||||
|
||||
&dsi {
|
||||
status = "okay";
|
||||
auto-calculation-mode;
|
||||
//rockchip,lane-rate = <1000>;
|
||||
// auto-calculation-mode;
|
||||
rockchip,lane-rate = <1150>;
|
||||
dsi_panel: panel@0 {
|
||||
status = "okay";
|
||||
compatible = "simple-panel-dsi";
|
||||
@@ -346,18 +346,18 @@
|
||||
39 00 1A B9 01 55 55 55 55 55 50 55 55 55 55 55 50 55 55 55 55 55 50 55 55 55 55 55 50
|
||||
39 00 10 BB 01 02 03 0A 04 13 14 12 16 5C 00 15 16 03 00
|
||||
39 00 1A BC FE F8 F0 00 00 00 00 04 00 05 80 02 23 00 C9 99 99 00 C4 09 C3 86 03 2E 11
|
||||
39 00 08 BD ED 23 42 52 52 1F 00
|
||||
39 00 08 BD 00 23 42 52 52 1F 00
|
||||
39 00 18 BE 5C 48 64 46 0A 88 58 33 33 33 93 00 DD DD 00 00 00 00 B2 AF B2 AF 00
|
||||
39 00 0B BF 0C 19 0C 19 00 11 22 04 58 00
|
||||
39 00 17 C0 40 90 17 41 23 56 F7 8A FF FF FF FF FF FF 3F FF 00 CC 02 00 01 B3
|
||||
39 00 17 C1 00 96 00 28 00 28 04 28 28 04 C7 80 0F 00 C1 22 7F C0 10 FF 0F E7
|
||||
39 00 0B BF 0C 19 0C 19 00 11 22 04 5D 07
|
||||
39 00 17 C0 40 90 17 12 34 F5 67 89 FF FF FF FF FF 3F 00 FF 00 CC 02 00 01 B3
|
||||
39 00 17 C1 00 96 00 28 00 28 04 28 28 04 C7 80 0F 00 C1 22 7F 80 10 FF 0F E7
|
||||
15 00 02 C2 00
|
||||
39 00 21 C3 00 FF 42 4D 01 00 00 00 00 00 00 00 00 B9 10 10 2A 2A 2A 2A 2A 2A 2A 2A 40 00 00 00 00 00 00 00
|
||||
39 00 0F C4 0C 35 28 49 00 3F 00 50 00 1F 00 A2 F0 E7
|
||||
39 00 21 C5 03 13 10 56 5D 38 04 05 08 04 19 00 B4 2C 2B 2B AF AF 20 00 02 00 80 0C 0C 06 13 64 FF 03 20 FF
|
||||
39 00 08 C8 42 00 48 EC E0 00 23
|
||||
39 00 05 D5 01 30 D8 10
|
||||
39 00 07 D7 3F 04 0A 00 00 06
|
||||
39 00 07 D7 3F 04 0A 00 00 0E
|
||||
//39 01 04 89 57 57 11
|
||||
39 00 1E C7 76 54 32 22 34 56 77 77 20 76 54 32 22 34 56 77 77 20 42 00 21 FF FF 04 04 03 0E 07 00
|
||||
39 00 21 80 E8 D5 B8 A0 8A 77 67 59 4C 20 FD E1 C9 B0 99 6F 4C 26 FF FC D6 AF 85 54 16 D3 AC 76 6A 59 46 37
|
||||
@@ -368,7 +368,6 @@
|
||||
39 00 03 F1 5A 59
|
||||
39 00 03 F0 A5 A6
|
||||
15 00 02 35 00
|
||||
|
||||
05 78 01 11
|
||||
05 0A 01 29
|
||||
15 00 02 AC 05
|
||||
@@ -423,7 +422,6 @@
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
&dsi_in_vp1 {
|
||||
@@ -463,7 +461,8 @@
|
||||
chipone,touch-earjack-detect-enable;
|
||||
chipone,touch-earjack-state-filepath = "/sys/bus/platform/drivers/Accdet_Driver/state";
|
||||
chipone,touch-earjack-poll-interval = <1000>;
|
||||
extcon = <&dsi>;
|
||||
|
||||
rockchip,panel-notifier = <&dsi_panel>;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/rockchip-panel-notifier.h>
|
||||
|
||||
#include <video/display_timing.h>
|
||||
#include <video/mipi_display.h>
|
||||
@@ -217,6 +218,8 @@ struct panel_simple {
|
||||
|
||||
struct drm_dsc_picture_parameter_set *pps;
|
||||
enum drm_panel_orientation orientation;
|
||||
|
||||
struct rockchip_panel_notifier panel_notifier;
|
||||
};
|
||||
|
||||
static inline void panel_simple_msleep(unsigned int msecs)
|
||||
@@ -530,6 +533,9 @@ int panel_simple_loader_protect(struct drm_panel *panel)
|
||||
p->prepared = true;
|
||||
p->enabled = true;
|
||||
|
||||
rockchip_panel_notifier_call_chain(&p->panel_notifier,
|
||||
PANEL_ENABLED, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(panel_simple_loader_protect);
|
||||
@@ -538,6 +544,13 @@ static int panel_simple_disable(struct drm_panel *panel)
|
||||
{
|
||||
struct panel_simple *p = to_panel_simple(panel);
|
||||
|
||||
/*
|
||||
* notify other devices (such as TP) to perform the action before the
|
||||
* panel is disabled.
|
||||
*/
|
||||
rockchip_panel_notifier_call_chain(&p->panel_notifier,
|
||||
PANEL_PRE_DISABLE, NULL);
|
||||
|
||||
if (!p->enabled)
|
||||
return 0;
|
||||
|
||||
@@ -641,6 +654,13 @@ static int panel_simple_enable(struct drm_panel *panel)
|
||||
|
||||
p->enabled = true;
|
||||
|
||||
/*
|
||||
* notify other devices (such as TP) to perform the action after the
|
||||
* panel is enabled.
|
||||
*/
|
||||
rockchip_panel_notifier_call_chain(&p->panel_notifier,
|
||||
PANEL_ENABLED, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -973,6 +993,9 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc)
|
||||
|
||||
dev_set_drvdata(dev, panel);
|
||||
|
||||
devm_rockchip_panel_notifier_register(dev, &panel->base,
|
||||
&panel->panel_notifier);
|
||||
|
||||
drm_panel_init(&panel->base, dev, &panel_simple_funcs, connector_type);
|
||||
|
||||
err = drm_panel_of_backlight(&panel->base);
|
||||
|
||||
@@ -129,6 +129,14 @@ config ROCKCHIP_LVDS
|
||||
support LVDS, rgb, dual LVDS output mode. say Y to enable its
|
||||
driver.
|
||||
|
||||
config ROCKCHIP_PANEL_NOTIFIER
|
||||
tristate "Rockchip panel notifier"
|
||||
depends on OF
|
||||
help
|
||||
Say Y here if you want to enable support for the panel notifier. The
|
||||
notifier is used to notify other devices (such as TP) to perform the
|
||||
corresponding action when the panel is in different actions.
|
||||
|
||||
config ROCKCHIP_RGB
|
||||
bool "Rockchip RGB support"
|
||||
depends on PINCTRL
|
||||
|
||||
@@ -28,6 +28,7 @@ rockchipdrm-$(CONFIG_ROCKCHIP_RK3066_HDMI) += rk3066_hdmi.o
|
||||
rockchipdrm-$(CONFIG_ROCKCHIP_VCONN) += rockchip_drm_vconn.o
|
||||
rockchipdrm-$(CONFIG_DRM_ROCKCHIP_VVOP) += rockchip_drm_vvop.o
|
||||
|
||||
obj-$(CONFIG_ROCKCHIP_PANEL_NOTIFIER) += rockchip_panel_notifier.o
|
||||
obj-$(CONFIG_ROCKCHIP_DW_HDCP2) += dw_hdcp2.o
|
||||
obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o
|
||||
obj-$(CONFIG_DRM_ROCKCHIP_RK618) += rk618/
|
||||
|
||||
@@ -2915,6 +2915,12 @@ static int dw_dp_encoder_atomic_check(struct drm_encoder *encoder,
|
||||
s->bus_flags = di->bus_flags;
|
||||
s->tv_state = &conn_state->tv;
|
||||
s->eotf = dp->eotf_type;
|
||||
|
||||
if (video->color_format == DRM_COLOR_FORMAT_RGB444)
|
||||
s->color_range = DRM_COLOR_YCBCR_FULL_RANGE;
|
||||
else
|
||||
s->color_range = DRM_COLOR_YCBCR_LIMITED_RANGE;
|
||||
|
||||
if (dw_dp_is_hdr_eotf(s->eotf))
|
||||
s->color_encoding = DRM_COLOR_YCBCR_BT2020;
|
||||
else
|
||||
|
||||
@@ -9113,39 +9113,68 @@ static int vop2_zpos_cmp(const void *a, const void *b)
|
||||
return pa->plane->base.id - pb->plane->base.id;
|
||||
}
|
||||
|
||||
static bool check_acm_state_changed(struct rockchip_crtc_state *new_vcstate,
|
||||
struct rockchip_crtc_state *old_vcstate,
|
||||
struct vop2_video_port *vp)
|
||||
static bool vop2_blob_changed(struct drm_property_blob *new_blob,
|
||||
struct drm_property_blob *old_blob)
|
||||
{
|
||||
/* blob is not created after boot */
|
||||
if (!old_blob && !new_blob)
|
||||
return false;
|
||||
|
||||
/* blob has been created */
|
||||
if (!old_blob && new_blob)
|
||||
return true;
|
||||
|
||||
/* blob has been destroyed */
|
||||
if (old_blob && !new_blob)
|
||||
return true;
|
||||
|
||||
/* blob data has been updated */
|
||||
if ((old_blob && new_blob) &&
|
||||
((new_blob->length != old_blob->length) ||
|
||||
memcmp(new_blob->data, old_blob->data, new_blob->length)))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool vop2_update_acm_info(struct vop2_video_port *vp,
|
||||
struct rockchip_crtc_state *new_vcstate,
|
||||
struct rockchip_crtc_state *old_vcstate)
|
||||
{
|
||||
struct drm_property_blob *old_blob = old_vcstate->acm_lut_data;
|
||||
struct drm_property_blob *new_blob = new_vcstate->acm_lut_data;
|
||||
struct post_acm *new_acm = NULL, *old_acm = NULL;
|
||||
bool ret;
|
||||
|
||||
ret = vop2_blob_changed(new_blob, old_blob);
|
||||
|
||||
if (!ret)
|
||||
return ret;
|
||||
|
||||
if (new_blob)
|
||||
new_acm = (struct post_acm *)new_blob->data;
|
||||
|
||||
if (old_blob)
|
||||
old_acm = (struct post_acm *)old_blob->data;
|
||||
|
||||
if (!old_acm && !new_acm)
|
||||
return false;
|
||||
|
||||
if (!old_acm && new_acm) {
|
||||
memcpy(&vp->acm_info, new_acm, sizeof(struct post_acm));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (old_acm && !new_acm) {
|
||||
memcpy(&vp->acm_info, new_blob->data, sizeof(struct post_acm));
|
||||
else
|
||||
memset(&vp->acm_info, 0, sizeof(struct post_acm));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (old_acm && new_acm && memcmp(new_acm, old_acm, sizeof(struct post_acm))) {
|
||||
memcpy(&vp->acm_info, new_acm, sizeof(struct post_acm));
|
||||
return true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
return false;
|
||||
static void vop2_update_post_csc_info(struct vop2_video_port *vp,
|
||||
struct rockchip_crtc_state *new_vcstate,
|
||||
struct rockchip_crtc_state *old_vcstate)
|
||||
{
|
||||
struct drm_property_blob *old_blob = old_vcstate->post_csc_data;
|
||||
struct drm_property_blob *new_blob = new_vcstate->post_csc_data;
|
||||
bool ret;
|
||||
|
||||
ret = vop2_blob_changed(new_blob, old_blob);
|
||||
|
||||
if (!ret)
|
||||
return;
|
||||
|
||||
if (new_blob)
|
||||
memcpy(&vp->csc_info, new_blob->data, sizeof(struct post_csc));
|
||||
else
|
||||
memset(&vp->csc_info, 0, sizeof(struct post_csc));
|
||||
}
|
||||
|
||||
static int vop2_crtc_atomic_check(struct drm_crtc *crtc,
|
||||
@@ -9178,7 +9207,9 @@ static int vop2_crtc_atomic_check(struct drm_crtc *crtc,
|
||||
else
|
||||
vp->refresh_rate_change = false;
|
||||
|
||||
if (check_acm_state_changed(new_vcstate, old_vcstate, vp) ||
|
||||
vop2_update_post_csc_info(vp, new_vcstate, old_vcstate);
|
||||
|
||||
if (vop2_update_acm_info(vp, new_vcstate, old_vcstate) ||
|
||||
new_crtc_state->active_changed)
|
||||
vp->acm_state_changed = true;
|
||||
else
|
||||
@@ -11042,21 +11073,6 @@ static void vop2_post_sharp_config(struct drm_crtc *crtc)
|
||||
vcstate->sharp_en = true;
|
||||
}
|
||||
|
||||
static void vop3_post_config(struct drm_crtc *crtc)
|
||||
{
|
||||
struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
|
||||
struct vop2_video_port *vp = to_vop2_video_port(crtc);
|
||||
struct post_csc *csc;
|
||||
|
||||
csc = vcstate->post_csc_data ? (struct post_csc *)vcstate->post_csc_data->data : NULL;
|
||||
if (csc && memcmp(&vp->csc_info, csc, sizeof(struct post_csc)))
|
||||
memcpy(&vp->csc_info, csc, sizeof(struct post_csc));
|
||||
vop3_post_csc_config(crtc, &vp->acm_info, vp->csc_info.csc_enable ? &vp->csc_info : NULL);
|
||||
|
||||
if (vp->acm_state_changed)
|
||||
vop3_post_acm_config(crtc, &vp->acm_info);
|
||||
}
|
||||
|
||||
static void vop2_cfg_update(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *old_crtc_state)
|
||||
{
|
||||
@@ -11110,8 +11126,13 @@ static void vop2_cfg_update(struct drm_crtc *crtc,
|
||||
|
||||
spin_unlock(&vop2->reg_lock);
|
||||
|
||||
if (vp_data->feature & (VOP_FEATURE_POST_ACM | VOP_FEATURE_POST_CSC))
|
||||
vop3_post_config(crtc);
|
||||
if (vp_data->feature & VOP_FEATURE_POST_CSC)
|
||||
vop3_post_csc_config(crtc, &vp->acm_info,
|
||||
vp->csc_info.csc_enable ? &vp->csc_info : NULL);
|
||||
|
||||
if ((vp_data->feature & VOP_FEATURE_POST_ACM) && vp->acm_state_changed)
|
||||
vop3_post_acm_config(crtc, &vp->acm_info);
|
||||
|
||||
}
|
||||
|
||||
static void vop2_sleep_scan_line_time(struct vop2_video_port *vp, int scan_line)
|
||||
|
||||
223
drivers/gpu/drm/rockchip/rockchip_panel_notifier.c
Normal file
223
drivers/gpu/drm/rockchip/rockchip_panel_notifier.c
Normal file
@@ -0,0 +1,223 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2024 Rockchip Electronics Co. Ltd.
|
||||
* Author: Zhibin Huang <zhibin.huang@rock-chips.com>
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/rockchip-panel-notifier.h>
|
||||
|
||||
#include <drm/drm_panel.h>
|
||||
|
||||
struct rockchip_panel_notifier_client {
|
||||
struct list_head list;
|
||||
struct rockchip_panel_notifier *pn;
|
||||
struct notifier_block *nb;
|
||||
};
|
||||
|
||||
static DEFINE_MUTEX(notifier_list_lock);
|
||||
static LIST_HEAD(notifier_list);
|
||||
static DEFINE_MUTEX(notifier_client_list_lock);
|
||||
static LIST_HEAD(notifier_client_list);
|
||||
|
||||
static int
|
||||
rockchip_panel_notifier_register_client(struct device *dev,
|
||||
struct rockchip_panel_notifier_client **client)
|
||||
{
|
||||
struct rockchip_panel_notifier_client *this = *client;
|
||||
struct rockchip_panel_notifier *pn;
|
||||
struct device_node *node;
|
||||
struct drm_panel *panel;
|
||||
int ret;
|
||||
|
||||
if (!dev || !dev->of_node || !this->nb)
|
||||
return -EINVAL;
|
||||
|
||||
node = of_parse_phandle(dev->of_node, "rockchip,panel-notifier", 0);
|
||||
if (!node)
|
||||
return -ENODEV;
|
||||
|
||||
panel = of_drm_find_panel(node);
|
||||
if (IS_ERR(panel)) {
|
||||
of_node_put(node);
|
||||
return PTR_ERR(panel);
|
||||
}
|
||||
|
||||
of_node_put(node);
|
||||
|
||||
mutex_lock(¬ifier_list_lock);
|
||||
list_for_each_entry(pn, ¬ifier_list, list) {
|
||||
if (pn->panel == panel)
|
||||
goto find;
|
||||
}
|
||||
pn = NULL;
|
||||
find:
|
||||
mutex_unlock(¬ifier_list_lock);
|
||||
if (!pn)
|
||||
return -ENODEV;
|
||||
|
||||
ret = blocking_notifier_chain_register(&pn->nh, this->nb);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
this->pn = pn;
|
||||
|
||||
mutex_lock(¬ifier_client_list_lock);
|
||||
list_add_tail(&this->list, ¬ifier_client_list);
|
||||
mutex_unlock(¬ifier_client_list_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
rockchip_panel_notifier_unregister_client(struct rockchip_panel_notifier_client *client)
|
||||
{
|
||||
if (!client)
|
||||
return;
|
||||
|
||||
blocking_notifier_chain_unregister(&client->pn->nh, client->nb);
|
||||
}
|
||||
|
||||
static void
|
||||
devm_rockchip_panel_notifier_unreg_client(struct device *dev, void *res)
|
||||
{
|
||||
struct rockchip_panel_notifier_client *pn_client, *next, *client = res;
|
||||
|
||||
mutex_lock(¬ifier_client_list_lock);
|
||||
list_for_each_entry_safe(pn_client, next, ¬ifier_client_list, list) {
|
||||
if (pn_client != client)
|
||||
continue;
|
||||
|
||||
rockchip_panel_notifier_unregister_client(pn_client);
|
||||
list_del_init(&pn_client->list);
|
||||
}
|
||||
mutex_unlock(¬ifier_client_list_lock);
|
||||
}
|
||||
|
||||
int devm_rockchip_panel_notifier_register_client(struct device *dev,
|
||||
struct notifier_block *nb)
|
||||
{
|
||||
int ret;
|
||||
struct rockchip_panel_notifier_client *pn_client;
|
||||
|
||||
if (!dev || !nb)
|
||||
return -EINVAL;
|
||||
|
||||
pn_client = devres_alloc(devm_rockchip_panel_notifier_unreg_client,
|
||||
sizeof(*pn_client), GFP_KERNEL);
|
||||
if (!pn_client)
|
||||
return -ENOMEM;
|
||||
|
||||
pn_client->nb = nb;
|
||||
|
||||
ret = rockchip_panel_notifier_register_client(dev, &pn_client);
|
||||
if (ret) {
|
||||
devres_free(pn_client);
|
||||
return ret;
|
||||
}
|
||||
|
||||
devres_add(dev, pn_client);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(devm_rockchip_panel_notifier_register_client);
|
||||
|
||||
void devm_rockchip_panel_notifier_unregister_client(struct device *dev)
|
||||
{
|
||||
WARN_ON(devres_release(dev, devm_rockchip_panel_notifier_unreg_client,
|
||||
NULL, NULL));
|
||||
}
|
||||
EXPORT_SYMBOL(devm_rockchip_panel_notifier_unregister_client);
|
||||
|
||||
static int rockchip_panel_notifier_register(struct drm_panel *panel,
|
||||
struct rockchip_panel_notifier *pn)
|
||||
{
|
||||
if (!panel || !pn)
|
||||
return -EINVAL;
|
||||
|
||||
pn->panel = panel;
|
||||
|
||||
BLOCKING_INIT_NOTIFIER_HEAD(&pn->nh);
|
||||
|
||||
mutex_lock(¬ifier_list_lock);
|
||||
list_add_tail(&pn->list, ¬ifier_list);
|
||||
mutex_unlock(¬ifier_list_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rockchip_panel_notifier_unregister(struct rockchip_panel_notifier *pn)
|
||||
{
|
||||
struct rockchip_panel_notifier_client *pn_client, *next;
|
||||
|
||||
if (!pn)
|
||||
return;
|
||||
|
||||
mutex_lock(¬ifier_client_list_lock);
|
||||
list_for_each_entry_safe(pn_client, next, ¬ifier_client_list, list) {
|
||||
if (pn_client->pn != pn)
|
||||
continue;
|
||||
|
||||
rockchip_panel_notifier_unregister_client(pn_client);
|
||||
list_del_init(&pn_client->list);
|
||||
}
|
||||
mutex_unlock(¬ifier_client_list_lock);
|
||||
|
||||
mutex_lock(¬ifier_list_lock);
|
||||
list_del_init(&pn->list);
|
||||
mutex_unlock(¬ifier_list_lock);
|
||||
}
|
||||
|
||||
static void devm_rockchip_panel_notifier_unreg(struct device *dev, void *res)
|
||||
{
|
||||
rockchip_panel_notifier_unregister(*(struct rockchip_panel_notifier **)res);
|
||||
}
|
||||
|
||||
void devm_rockchip_panel_notifier_unregister(struct device *dev)
|
||||
{
|
||||
WARN_ON(devres_release(dev, devm_rockchip_panel_notifier_unreg,
|
||||
NULL, NULL));
|
||||
}
|
||||
EXPORT_SYMBOL(devm_rockchip_panel_notifier_unregister);
|
||||
|
||||
int devm_rockchip_panel_notifier_register(struct device *dev,
|
||||
struct drm_panel *panel,
|
||||
struct rockchip_panel_notifier *pn)
|
||||
{
|
||||
int ret;
|
||||
struct rockchip_panel_notifier **ptr;
|
||||
|
||||
ptr = devres_alloc(devm_rockchip_panel_notifier_unreg, sizeof(*ptr),
|
||||
GFP_KERNEL);
|
||||
if (!ptr)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = rockchip_panel_notifier_register(panel, pn);
|
||||
if (ret) {
|
||||
devres_free(ptr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
*ptr = pn;
|
||||
devres_add(dev, ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(devm_rockchip_panel_notifier_register);
|
||||
|
||||
int rockchip_panel_notifier_call_chain(struct rockchip_panel_notifier *pn,
|
||||
enum rockchip_panel_event panel_event,
|
||||
struct rockchip_panel_edata *panel_edata)
|
||||
{
|
||||
if (!pn)
|
||||
return -EINVAL;
|
||||
|
||||
return blocking_notifier_call_chain(&pn->nh, (unsigned long)panel_event,
|
||||
(void *)panel_edata);
|
||||
}
|
||||
EXPORT_SYMBOL(rockchip_panel_notifier_call_chain);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Zhibin Huang <zhibin.huang@rock-chips.com>");
|
||||
MODULE_DESCRIPTION("rockchip panel notifier");
|
||||
@@ -4,9 +4,10 @@
|
||||
#
|
||||
|
||||
config TOUCHSCREEN_CHIPONE_9551R
|
||||
tristate "chipone Touchscreen"
|
||||
depends on I2C
|
||||
default n
|
||||
help
|
||||
Say Y here if you have chipone touch panel.
|
||||
If unsure, say N.
|
||||
tristate "chipone Touchscreen"
|
||||
depends on I2C
|
||||
select ROCKCHIP_PANEL_NOTIFIER
|
||||
default n
|
||||
help
|
||||
Say Y here if you have chipone touch panel.
|
||||
If unsure, say N.
|
||||
|
||||
@@ -18,18 +18,15 @@
|
||||
/* Support cascade application */
|
||||
//#define CFG_CTS_CASCADE_SUPPORTED
|
||||
|
||||
/* Support RK dsi extcon notifier for suspend and resume */
|
||||
//#define CONFIG_PM_DSI_EXTCON_NOTIFIER
|
||||
|
||||
/* Support both finger and stylus protocol, 11 */
|
||||
// #define CFG_CTS_FINGER_STYLUS_SUPPORTED
|
||||
|
||||
/* #define CFG_CTS_STYLUS_BTN_SUPPORTED */
|
||||
|
||||
#define CONFIG_CTS_I2C_HOST
|
||||
#define CONFIG_CTS_I2C_HOST
|
||||
|
||||
/* For Goole Security */
|
||||
#define CFG_CTS_FOR_GKI
|
||||
#define CFG_CTS_FOR_GKI
|
||||
|
||||
/** Whether reset pin is used */
|
||||
#define CFG_CTS_HAS_RESET_PIN
|
||||
|
||||
@@ -3,10 +3,9 @@
|
||||
#ifndef CTS_CORE_H
|
||||
#define CTS_CORE_H
|
||||
|
||||
#include <linux/rockchip-panel-notifier.h>
|
||||
|
||||
#include "cts_config.h"
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
|
||||
enum cts_dev_hw_reg {
|
||||
CTS_DEV_HW_REG_HARDWARE_ID = 0x70000u,
|
||||
@@ -528,14 +527,8 @@ struct chipone_ts_data {
|
||||
|
||||
bool force_reflash;
|
||||
// struct kobject *suspend_kobj;
|
||||
#ifdef CONFIG_PM_DSI_EXTCON_NOTIFIER
|
||||
struct extcon_dev *edev;
|
||||
struct notifier_block extcon_nb;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
struct early_suspend early_suspend;
|
||||
#endif
|
||||
struct notifier_block panel_nb;
|
||||
};
|
||||
|
||||
/*static inline u32 get_unaligned_le24(const void *p)
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#else
|
||||
#define LOG_TAG "SPIDrv"
|
||||
#endif
|
||||
#include <linux/extcon.h>
|
||||
#include "cts_config.h"
|
||||
#include "cts_platform.h"
|
||||
#include "cts_core.h"
|
||||
@@ -348,49 +347,22 @@ static int cts_get_panel(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_DSI_EXTCON_NOTIFIER
|
||||
static int ts_extcon_notifier(struct notifier_block *self,
|
||||
unsigned long event, void *data)
|
||||
static int rockchip_panel_notifier_call(struct notifier_block *self,
|
||||
unsigned long val, void *v)
|
||||
{
|
||||
enum rockchip_panel_event event = (enum rockchip_panel_event)val;
|
||||
struct chipone_ts_data *cts_data =
|
||||
container_of(self, struct chipone_ts_data, extcon_nb);
|
||||
if (extcon_get_state(cts_data->edev, EXTCON_JACK_VIDEO_OUT)){
|
||||
pr_info("%s %d\n", __func__, __LINE__);
|
||||
//cts_plat_set_reset(cts_data->pdata, 1);
|
||||
//mdelay(1);
|
||||
//cts_plat_set_reset(cts_data->pdata, 0);
|
||||
//mdelay(5);/* 1ms */
|
||||
//cts_plat_set_reset(cts_data->pdata, 1);
|
||||
container_of(self, struct chipone_ts_data, panel_nb);
|
||||
|
||||
if (event == PANEL_ENABLED) {
|
||||
cts_info("notify to resume");
|
||||
cts_resume(cts_data);
|
||||
} else {
|
||||
} else if (event == PANEL_PRE_DISABLE) {
|
||||
cts_info("notify to suspend");
|
||||
cts_suspend(cts_data);
|
||||
pr_info("%s %d\n", __func__, __LINE__);
|
||||
//cts_plat_set_reset(cts_data->pdata, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
/* earlysuspend module the suspend/resume procedure */
|
||||
static void cts_ts_early_suspend(struct early_suspend *h)
|
||||
{
|
||||
struct chipone_ts_data *cts_data = container_of(h, struct chipone_ts_data, early_suspend);
|
||||
|
||||
pr_info("%s %d\n", __func__, __LINE__);
|
||||
flush_work(&cts_data->ts_resume_work);
|
||||
cts_suspend(cts_data);
|
||||
}
|
||||
|
||||
static void cts_ts_late_resume(struct early_suspend *h)
|
||||
{
|
||||
struct chipone_ts_data *cts_data = container_of(h, struct chipone_ts_data, early_suspend);
|
||||
|
||||
pr_info("%s %d\n", __func__, __LINE__);
|
||||
queue_work(cts_data->workqueue, &cts_data->ts_resume_work);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CTS_I2C_HOST
|
||||
static int cts_driver_probe(struct i2c_client *client,
|
||||
@@ -635,33 +607,15 @@ static int cts_driver_probe(struct spi_device *client)
|
||||
#endif /* CONFIG_MTK_PLATFORM */
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
cts_data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
|
||||
cts_data->early_suspend.suspend = cts_ts_early_suspend;
|
||||
cts_data->early_suspend.resume = cts_ts_late_resume;
|
||||
register_early_suspend(&cts_data->early_suspend);
|
||||
#endif
|
||||
cts_data->panel_nb.notifier_call = rockchip_panel_notifier_call;
|
||||
|
||||
#ifdef CONFIG_PM_DSI_EXTCON_NOTIFIER
|
||||
cts_data->edev = extcon_get_edev_by_phandle(&client->dev, 0);
|
||||
if (IS_ERR(cts_data->edev)) {
|
||||
if (PTR_ERR(cts_data->edev) != -EPROBE_DEFER)
|
||||
dev_err(&client->dev, "Invalid or missing extcon\n");
|
||||
pr_info("register notifier...but extcon_get_edev error\n");
|
||||
return 0;
|
||||
ret = devm_rockchip_panel_notifier_register_client(&client->dev,
|
||||
&cts_data->panel_nb);
|
||||
if (ret) {
|
||||
cts_err("failed to register notifier client for TP: %d\n", ret);
|
||||
goto err_deinit_oem;
|
||||
}
|
||||
|
||||
cts_data->extcon_nb.notifier_call = ts_extcon_notifier;
|
||||
ret = extcon_register_notifier(cts_data->edev, EXTCON_JACK_VIDEO_OUT,
|
||||
&cts_data->extcon_nb);
|
||||
pr_info("register notifier...\n");
|
||||
if (ret < 0) {
|
||||
pr_info("fail to register notifier...\n");
|
||||
dev_err(&client->dev, "failed to register notifier for TP\n");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
err_deinit_oem:
|
||||
@@ -783,10 +737,6 @@ static void cts_driver_remove(struct spi_device *client)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
unregister_early_suspend(&cts_data->early_suspend);
|
||||
#endif
|
||||
|
||||
cts_tool_deinit(cts_data);
|
||||
|
||||
cts_sysfs_remove_device(&client->dev);
|
||||
|
||||
@@ -740,6 +740,18 @@ config VIDEO_IMX492
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called imx492.
|
||||
|
||||
config VIDEO_IMX498
|
||||
tristate "Sony IMX498 sensor support"
|
||||
depends on I2C && VIDEO_DEV
|
||||
depends on MEDIA_CAMERA_SUPPORT
|
||||
select VIDEO_V4L2_SUBDEV_API
|
||||
help
|
||||
This is a Video4Linux2 sensor driver for the Sony
|
||||
IMX498 camera.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called imx498.
|
||||
|
||||
config VIDEO_IMX577
|
||||
tristate "Sony IMX577 sensor support"
|
||||
depends on I2C && VIDEO_DEV
|
||||
|
||||
@@ -98,6 +98,7 @@ obj-$(CONFIG_VIDEO_IMX412) += imx412.o
|
||||
obj-$(CONFIG_VIDEO_IMX415) += imx415.o
|
||||
obj-$(CONFIG_VIDEO_IMX464) += imx464.o
|
||||
obj-$(CONFIG_VIDEO_IMX492) += imx492.o
|
||||
obj-$(CONFIG_VIDEO_IMX492) += imx498.o
|
||||
obj-$(CONFIG_VIDEO_IMX577) += imx577.o
|
||||
obj-$(CONFIG_VIDEO_IMX586) += imx586.o
|
||||
obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o
|
||||
|
||||
@@ -65,6 +65,8 @@ struct ces6301_device {
|
||||
struct regulator *supply;
|
||||
struct i2c_client *client;
|
||||
bool power_on;
|
||||
|
||||
atomic_t open_cnt;
|
||||
};
|
||||
|
||||
struct TimeTabel_s {
|
||||
@@ -532,22 +534,24 @@ static int ces6301_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
||||
return rval;
|
||||
}
|
||||
|
||||
ces6301_init(client);
|
||||
if (dev_vcm->power_on && atomic_inc_return(&dev_vcm->open_cnt) == 1) {
|
||||
ces6301_init(client);
|
||||
|
||||
dev_dbg(&client->dev, "%s: current_lens_pos %d, current_related_pos %d\n",
|
||||
__func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos);
|
||||
move_time = 1000 * ces6301_move_time(dev_vcm, CES6301_GRADUAL_MOVELENS_STEPS);
|
||||
while (dac <= dev_vcm->current_lens_pos) {
|
||||
ces6301_set_dac(dev_vcm, dac);
|
||||
usleep_range(move_time, move_time + 1000);
|
||||
dac += CES6301_GRADUAL_MOVELENS_STEPS;
|
||||
if (dac >= dev_vcm->current_lens_pos)
|
||||
break;
|
||||
}
|
||||
dev_dbg(&client->dev, "%s: current_lens_pos %d, current_related_pos %d\n",
|
||||
__func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos);
|
||||
move_time = 1000 * ces6301_move_time(dev_vcm, CES6301_GRADUAL_MOVELENS_STEPS);
|
||||
while (dac <= dev_vcm->current_lens_pos) {
|
||||
ces6301_set_dac(dev_vcm, dac);
|
||||
usleep_range(move_time, move_time + 1000);
|
||||
dac += CES6301_GRADUAL_MOVELENS_STEPS;
|
||||
if (dac >= dev_vcm->current_lens_pos)
|
||||
break;
|
||||
}
|
||||
|
||||
if (dac > dev_vcm->current_lens_pos) {
|
||||
dac = dev_vcm->current_lens_pos;
|
||||
ces6301_set_dac(dev_vcm, dac);
|
||||
if (dac > dev_vcm->current_lens_pos) {
|
||||
dac = dev_vcm->current_lens_pos;
|
||||
ces6301_set_dac(dev_vcm, dac);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -560,20 +564,22 @@ static int ces6301_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
||||
int dac = dev_vcm->current_lens_pos;
|
||||
unsigned int move_time;
|
||||
|
||||
dev_dbg(&client->dev, "%s: current_lens_pos %d, current_related_pos %d\n",
|
||||
__func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos);
|
||||
move_time = 1000 * ces6301_move_time(dev_vcm, CES6301_GRADUAL_MOVELENS_STEPS);
|
||||
while (dac >= 0) {
|
||||
ces6301_set_dac(dev_vcm, dac);
|
||||
usleep_range(move_time, move_time + 1000);
|
||||
dac -= CES6301_GRADUAL_MOVELENS_STEPS;
|
||||
if (dac <= 0)
|
||||
break;
|
||||
}
|
||||
if (dev_vcm->power_on && atomic_dec_return(&dev_vcm->open_cnt) == 0) {
|
||||
dev_dbg(&client->dev, "%s: current_lens_pos %d, current_related_pos %d\n",
|
||||
__func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos);
|
||||
move_time = 1000 * ces6301_move_time(dev_vcm, CES6301_GRADUAL_MOVELENS_STEPS);
|
||||
while (dac >= 0) {
|
||||
ces6301_set_dac(dev_vcm, dac);
|
||||
usleep_range(move_time, move_time + 1000);
|
||||
dac -= CES6301_GRADUAL_MOVELENS_STEPS;
|
||||
if (dac <= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (dac < 0) {
|
||||
dac = 0;
|
||||
ces6301_set_dac(dev_vcm, dac);
|
||||
if (dac < 0) {
|
||||
dac = 0;
|
||||
ces6301_set_dac(dev_vcm, dac);
|
||||
}
|
||||
}
|
||||
|
||||
pm_runtime_put(sd->dev);
|
||||
@@ -1053,6 +1059,7 @@ static int ces6301_probe(struct i2c_client *client,
|
||||
ces6301_dev->end_move_tv = ns_to_kernel_old_timeval(ktime_get_ns());
|
||||
ces6301_dev->vcm_movefull_t =
|
||||
ces6301_move_time(ces6301_dev, CES6301_MAX_REG);
|
||||
atomic_set(&ces6301_dev->open_cnt, 0);
|
||||
pm_runtime_enable(&client->dev);
|
||||
|
||||
add_sysfs_interfaces(&client->dev);
|
||||
|
||||
@@ -113,6 +113,8 @@ struct cn3927v_device {
|
||||
struct regulator *supply;
|
||||
struct i2c_client *client;
|
||||
bool power_on;
|
||||
|
||||
atomic_t open_cnt;
|
||||
};
|
||||
|
||||
struct TimeTabel_s {
|
||||
@@ -675,24 +677,26 @@ static int cn3927v_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
||||
return rval;
|
||||
}
|
||||
|
||||
cn3927v_init(client);
|
||||
if (dev_vcm->power_on && atomic_inc_return(&dev_vcm->open_cnt) == 1) {
|
||||
cn3927v_init(client);
|
||||
|
||||
usleep_range(1000, 1200);
|
||||
v4l2_dbg(1, debug, sd, "%s: current_lens_pos %d, current_related_pos %d\n",
|
||||
__func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos);
|
||||
usleep_range(1000, 1200);
|
||||
v4l2_dbg(1, debug, sd, "%s: current_lens_pos %d, current_related_pos %d\n",
|
||||
__func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos);
|
||||
|
||||
move_time = 1000 * cn3927v_move_time(dev_vcm, CN3927V_GRADUAL_MOVELENS_STEPS);
|
||||
while (dac <= dev_vcm->current_lens_pos) {
|
||||
cn3927v_set_dac(dev_vcm, dac);
|
||||
usleep_range(move_time, move_time + 1000);
|
||||
dac += CN3927V_GRADUAL_MOVELENS_STEPS;
|
||||
if (dac >= dev_vcm->current_lens_pos)
|
||||
break;
|
||||
}
|
||||
move_time = 1000 * cn3927v_move_time(dev_vcm, CN3927V_GRADUAL_MOVELENS_STEPS);
|
||||
while (dac <= dev_vcm->current_lens_pos) {
|
||||
cn3927v_set_dac(dev_vcm, dac);
|
||||
usleep_range(move_time, move_time + 1000);
|
||||
dac += CN3927V_GRADUAL_MOVELENS_STEPS;
|
||||
if (dac >= dev_vcm->current_lens_pos)
|
||||
break;
|
||||
}
|
||||
|
||||
if (dac > dev_vcm->current_lens_pos) {
|
||||
dac = dev_vcm->current_lens_pos;
|
||||
cn3927v_set_dac(dev_vcm, dac);
|
||||
if (dac > dev_vcm->current_lens_pos) {
|
||||
dac = dev_vcm->current_lens_pos;
|
||||
cn3927v_set_dac(dev_vcm, dac);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
@@ -715,27 +719,29 @@ static int cn3927v_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
||||
atomic_read(&sd->dev->power.usage_count));
|
||||
#endif
|
||||
|
||||
v4l2_dbg(1, debug, sd, "%s: current_lens_pos %d, current_related_pos %d\n",
|
||||
__func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos);
|
||||
move_time = 1000 * cn3927v_move_time(dev_vcm, CN3927V_GRADUAL_MOVELENS_STEPS);
|
||||
while (dac >= CN3927V_GRADUAL_MOVELENS_STEPS) {
|
||||
cn3927v_set_dac(dev_vcm, dac);
|
||||
usleep_range(move_time, move_time + 1000);
|
||||
dac -= CN3927V_GRADUAL_MOVELENS_STEPS;
|
||||
if (dac <= 0)
|
||||
break;
|
||||
}
|
||||
if (dev_vcm->power_on && atomic_dec_return(&dev_vcm->open_cnt) == 0) {
|
||||
v4l2_dbg(1, debug, sd, "%s: current_lens_pos %d, current_related_pos %d\n",
|
||||
__func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos);
|
||||
move_time = 1000 * cn3927v_move_time(dev_vcm, CN3927V_GRADUAL_MOVELENS_STEPS);
|
||||
while (dac >= CN3927V_GRADUAL_MOVELENS_STEPS) {
|
||||
cn3927v_set_dac(dev_vcm, dac);
|
||||
usleep_range(move_time, move_time + 1000);
|
||||
dac -= CN3927V_GRADUAL_MOVELENS_STEPS;
|
||||
if (dac <= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (dac < CN3927V_GRADUAL_MOVELENS_STEPS) {
|
||||
dac = CN3927V_GRADUAL_MOVELENS_STEPS;
|
||||
cn3927v_set_dac(dev_vcm, dac);
|
||||
}
|
||||
/* set to power down mode */
|
||||
if (dev_vcm->adcanced_mode) {
|
||||
cn3927v_write_reg(client, 0x02, 1, 0x01);
|
||||
} else {
|
||||
/* Ringing off */
|
||||
cn3927v_write_msg(client, 0xDC, 0x51);
|
||||
if (dac < CN3927V_GRADUAL_MOVELENS_STEPS) {
|
||||
dac = CN3927V_GRADUAL_MOVELENS_STEPS;
|
||||
cn3927v_set_dac(dev_vcm, dac);
|
||||
}
|
||||
/* set to power down mode */
|
||||
if (dev_vcm->adcanced_mode) {
|
||||
cn3927v_write_reg(client, 0x02, 1, 0x01);
|
||||
} else {
|
||||
/* Ringing off */
|
||||
cn3927v_write_msg(client, 0xDC, 0x51);
|
||||
}
|
||||
}
|
||||
|
||||
pm_runtime_put(sd->dev);
|
||||
@@ -1333,6 +1339,7 @@ static int cn3927v_probe(struct i2c_client *client,
|
||||
cn3927v_dev->end_move_tv = ns_to_kernel_old_timeval(ktime_get_ns());
|
||||
cn3927v_dev->vcm_movefull_t =
|
||||
cn3927v_move_time(cn3927v_dev, CN3927V_MAX_REG);
|
||||
atomic_set(&cn3927v_dev->open_cnt, 0);
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
|
||||
@@ -99,6 +99,8 @@ struct dw9714_device {
|
||||
struct regulator *supply;
|
||||
struct i2c_client *client;
|
||||
bool power_on;
|
||||
|
||||
atomic_t open_cnt;
|
||||
};
|
||||
|
||||
struct TimeTabel_s {
|
||||
@@ -735,22 +737,24 @@ static int dw9714_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
||||
return rval;
|
||||
}
|
||||
|
||||
dw9714_init(client);
|
||||
if (dev_vcm->power_on && atomic_inc_return(&dev_vcm->open_cnt) == 1) {
|
||||
dw9714_init(client);
|
||||
|
||||
dev_dbg(&client->dev, "%s: current_lens_pos %d, current_related_pos %d\n",
|
||||
__func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos);
|
||||
move_time = 1000 * dw9714_move_time(dev_vcm, DW9714_GRADUAL_MOVELENS_STEPS);
|
||||
while (dac <= dev_vcm->current_lens_pos) {
|
||||
dw9714_set_dac(dev_vcm, dac);
|
||||
usleep_range(move_time, move_time + 1000);
|
||||
dac += DW9714_GRADUAL_MOVELENS_STEPS;
|
||||
if (dac >= dev_vcm->current_lens_pos)
|
||||
break;
|
||||
}
|
||||
dev_dbg(&client->dev, "%s: current_lens_pos %d, current_related_pos %d\n",
|
||||
__func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos);
|
||||
move_time = 1000 * dw9714_move_time(dev_vcm, DW9714_GRADUAL_MOVELENS_STEPS);
|
||||
while (dac <= dev_vcm->current_lens_pos) {
|
||||
dw9714_set_dac(dev_vcm, dac);
|
||||
usleep_range(move_time, move_time + 1000);
|
||||
dac += DW9714_GRADUAL_MOVELENS_STEPS;
|
||||
if (dac >= dev_vcm->current_lens_pos)
|
||||
break;
|
||||
}
|
||||
|
||||
if (dac > dev_vcm->current_lens_pos) {
|
||||
dac = dev_vcm->current_lens_pos;
|
||||
dw9714_set_dac(dev_vcm, dac);
|
||||
if (dac > dev_vcm->current_lens_pos) {
|
||||
dac = dev_vcm->current_lens_pos;
|
||||
dw9714_set_dac(dev_vcm, dac);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -763,20 +767,22 @@ static int dw9714_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
||||
int dac = dev_vcm->current_lens_pos;
|
||||
unsigned int move_time;
|
||||
|
||||
dev_dbg(&client->dev, "%s: current_lens_pos %d, current_related_pos %d\n",
|
||||
__func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos);
|
||||
move_time = 1000 * dw9714_move_time(dev_vcm, DW9714_GRADUAL_MOVELENS_STEPS);
|
||||
while (dac >= 0) {
|
||||
dw9714_set_dac(dev_vcm, dac);
|
||||
usleep_range(move_time, move_time + 1000);
|
||||
dac -= DW9714_GRADUAL_MOVELENS_STEPS;
|
||||
if (dac <= 0)
|
||||
break;
|
||||
}
|
||||
if (dev_vcm->power_on && atomic_dec_return(&dev_vcm->open_cnt) == 0) {
|
||||
dev_dbg(&client->dev, "%s: current_lens_pos %d, current_related_pos %d\n",
|
||||
__func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos);
|
||||
move_time = 1000 * dw9714_move_time(dev_vcm, DW9714_GRADUAL_MOVELENS_STEPS);
|
||||
while (dac >= 0) {
|
||||
dw9714_set_dac(dev_vcm, dac);
|
||||
usleep_range(move_time, move_time + 1000);
|
||||
dac -= DW9714_GRADUAL_MOVELENS_STEPS;
|
||||
if (dac <= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (dac < 0) {
|
||||
dac = 0;
|
||||
dw9714_set_dac(dev_vcm, dac);
|
||||
if (dac < 0) {
|
||||
dac = 0;
|
||||
dw9714_set_dac(dev_vcm, dac);
|
||||
}
|
||||
}
|
||||
|
||||
pm_runtime_put(sd->dev);
|
||||
@@ -1346,6 +1352,7 @@ static int dw9714_probe(struct i2c_client *client,
|
||||
dw9714_dev->end_move_tv = ns_to_kernel_old_timeval(ktime_get_ns());
|
||||
dw9714_dev->vcm_movefull_t =
|
||||
dw9714_move_time(dw9714_dev, DW9714_MAX_REG);
|
||||
atomic_set(&dw9714_dev->open_cnt, 0);
|
||||
pm_runtime_enable(&client->dev);
|
||||
|
||||
add_sysfs_interfaces(&client->dev);
|
||||
|
||||
@@ -77,6 +77,8 @@ struct dw9763_device {
|
||||
struct mutex lock;
|
||||
struct regulator *supply;
|
||||
bool power_on;
|
||||
|
||||
atomic_t open_cnt;
|
||||
};
|
||||
|
||||
static inline struct dw9763_device *to_dw9763_vcm(struct v4l2_ctrl *ctrl)
|
||||
@@ -405,23 +407,25 @@ static int dw9763_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
||||
return rval;
|
||||
}
|
||||
|
||||
dw9763_init(client);
|
||||
if (dev_vcm->power_on && atomic_inc_return(&dev_vcm->open_cnt) == 1) {
|
||||
dw9763_init(client);
|
||||
|
||||
v4l2_dbg(1, debug, sd, "%s: current_lens_pos %d, current_related_pos %d\n",
|
||||
__func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos);
|
||||
v4l2_dbg(1, debug, sd, "%s: current_lens_pos %d, current_related_pos %d\n",
|
||||
__func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos);
|
||||
|
||||
move_time = 1000 * dw9763_move_time(dev_vcm, DW9763_GRADUAL_MOVELENS_STEPS);
|
||||
while (dac <= dev_vcm->current_lens_pos) {
|
||||
dw9763_set_dac(dev_vcm, dac);
|
||||
usleep_range(move_time, move_time + 100);
|
||||
dac += DW9763_GRADUAL_MOVELENS_STEPS;
|
||||
if (dac > dev_vcm->current_lens_pos)
|
||||
break;
|
||||
}
|
||||
move_time = 1000 * dw9763_move_time(dev_vcm, DW9763_GRADUAL_MOVELENS_STEPS);
|
||||
while (dac <= dev_vcm->current_lens_pos) {
|
||||
dw9763_set_dac(dev_vcm, dac);
|
||||
usleep_range(move_time, move_time + 100);
|
||||
dac += DW9763_GRADUAL_MOVELENS_STEPS;
|
||||
if (dac > dev_vcm->current_lens_pos)
|
||||
break;
|
||||
}
|
||||
|
||||
if (dac > dev_vcm->current_lens_pos) {
|
||||
dac = dev_vcm->current_lens_pos;
|
||||
dw9763_set_dac(dev_vcm, dac);
|
||||
if (dac > dev_vcm->current_lens_pos) {
|
||||
dac = dev_vcm->current_lens_pos;
|
||||
dw9763_set_dac(dev_vcm, dac);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
@@ -444,27 +448,29 @@ static int dw9763_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
||||
atomic_read(&sd->dev->power.usage_count));
|
||||
#endif
|
||||
|
||||
v4l2_dbg(1, debug, sd, "%s: current_lens_pos %d, current_related_pos %d\n",
|
||||
__func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos);
|
||||
if (dev_vcm->power_on && atomic_dec_return(&dev_vcm->open_cnt) == 0) {
|
||||
v4l2_dbg(1, debug, sd, "%s: current_lens_pos %d, current_related_pos %d\n",
|
||||
__func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos);
|
||||
|
||||
dac -= DW9763_GRADUAL_MOVELENS_STEPS;
|
||||
move_time = 1000 * dw9763_move_time(dev_vcm, DW9763_GRADUAL_MOVELENS_STEPS);
|
||||
while (dac >= DW9763_GRADUAL_MOVELENS_STEPS) {
|
||||
dw9763_set_dac(dev_vcm, dac);
|
||||
usleep_range(move_time, move_time + 1000);
|
||||
dac -= DW9763_GRADUAL_MOVELENS_STEPS;
|
||||
if (dac <= 0)
|
||||
break;
|
||||
}
|
||||
move_time = 1000 * dw9763_move_time(dev_vcm, DW9763_GRADUAL_MOVELENS_STEPS);
|
||||
while (dac >= DW9763_GRADUAL_MOVELENS_STEPS) {
|
||||
dw9763_set_dac(dev_vcm, dac);
|
||||
usleep_range(move_time, move_time + 1000);
|
||||
dac -= DW9763_GRADUAL_MOVELENS_STEPS;
|
||||
if (dac <= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (dac < DW9763_GRADUAL_MOVELENS_STEPS) {
|
||||
dac = DW9763_GRADUAL_MOVELENS_STEPS / 2;
|
||||
dw9763_set_dac(dev_vcm, dac);
|
||||
if (dac < DW9763_GRADUAL_MOVELENS_STEPS) {
|
||||
dac = DW9763_GRADUAL_MOVELENS_STEPS / 2;
|
||||
dw9763_set_dac(dev_vcm, dac);
|
||||
}
|
||||
/* set to power down mode */
|
||||
ret = dw9763_write_reg(client, 0x02, 1, 0x01);
|
||||
if (ret)
|
||||
dev_err(&client->dev, "failed to set power down mode!\n");
|
||||
}
|
||||
/* set to power down mode */
|
||||
ret = dw9763_write_reg(client, 0x02, 1, 0x01);
|
||||
if (ret)
|
||||
dev_err(&client->dev, "failed to set power down mode!\n");
|
||||
|
||||
pm_runtime_put(sd->dev);
|
||||
#ifdef CONFIG_PM
|
||||
@@ -926,6 +932,7 @@ static int dw9763_probe(struct i2c_client *client,
|
||||
|
||||
dw9763_dev->vcm_movefull_t =
|
||||
dw9763_move_time(dw9763_dev, DW9763_MAX_REG);
|
||||
atomic_set(&dw9763_dev->open_cnt, 0);
|
||||
pm_runtime_set_active(&client->dev);
|
||||
pm_runtime_enable(&client->dev);
|
||||
pm_runtime_idle(&client->dev);
|
||||
|
||||
@@ -85,6 +85,7 @@ struct dw9800v_device {
|
||||
struct i2c_client *client;
|
||||
bool power_on;
|
||||
|
||||
atomic_t open_cnt;
|
||||
};
|
||||
|
||||
static inline struct dw9800v_device *to_dw9800v_vcm(struct v4l2_ctrl *ctrl)
|
||||
@@ -426,24 +427,27 @@ static int dw9800v_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
||||
pm_runtime_put_noidle(sd->dev);
|
||||
return rval;
|
||||
}
|
||||
dw9800v_init(client);
|
||||
|
||||
usleep_range(1000, 1200);
|
||||
v4l2_dbg(1, debug, sd, "%s: current_lens_pos %d, current_related_pos %d\n",
|
||||
__func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos);
|
||||
if (dev_vcm->power_on && atomic_inc_return(&dev_vcm->open_cnt) == 1) {
|
||||
dw9800v_init(client);
|
||||
|
||||
move_time = dw9800v_move_time(dev_vcm, DW9800V_GRADUAL_MOVELENS_STEPS);
|
||||
while (dac <= dev_vcm->current_lens_pos) {
|
||||
dw9800v_set_dac(dev_vcm, dac);
|
||||
usleep_range(move_time, move_time + 1000);
|
||||
dac += DW9800V_GRADUAL_MOVELENS_STEPS;
|
||||
if (dac >= dev_vcm->current_lens_pos)
|
||||
break;
|
||||
}
|
||||
usleep_range(1000, 1200);
|
||||
v4l2_dbg(1, debug, sd, "%s: current_lens_pos %d, current_related_pos %d\n",
|
||||
__func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos);
|
||||
|
||||
if (dac > dev_vcm->current_lens_pos) {
|
||||
dac = dev_vcm->current_lens_pos;
|
||||
dw9800v_set_dac(dev_vcm, dac);
|
||||
move_time = dw9800v_move_time(dev_vcm, DW9800V_GRADUAL_MOVELENS_STEPS);
|
||||
while (dac <= dev_vcm->current_lens_pos) {
|
||||
dw9800v_set_dac(dev_vcm, dac);
|
||||
usleep_range(move_time, move_time + 1000);
|
||||
dac += DW9800V_GRADUAL_MOVELENS_STEPS;
|
||||
if (dac >= dev_vcm->current_lens_pos)
|
||||
break;
|
||||
}
|
||||
|
||||
if (dac > dev_vcm->current_lens_pos) {
|
||||
dac = dev_vcm->current_lens_pos;
|
||||
dw9800v_set_dac(dev_vcm, dac);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
@@ -465,23 +469,25 @@ static int dw9800v_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
||||
v4l2_info(sd, "%s: enter, power.usage_count(%d)!\n", __func__,
|
||||
atomic_read(&sd->dev->power.usage_count));
|
||||
#endif
|
||||
v4l2_dbg(1, debug, sd, "%s: current_lens_pos %d, current_related_pos %d\n",
|
||||
__func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos);
|
||||
move_time = dw9800v_move_time(dev_vcm, DW9800V_GRADUAL_MOVELENS_STEPS);
|
||||
while (dac >= DW9800V_GRADUAL_MOVELENS_STEPS) {
|
||||
dw9800v_set_dac(dev_vcm, dac);
|
||||
usleep_range(move_time, move_time + 1000);
|
||||
dac -= DW9800V_GRADUAL_MOVELENS_STEPS;
|
||||
if (dac <= 0)
|
||||
break;
|
||||
}
|
||||
if (dev_vcm->power_on && atomic_dec_return(&dev_vcm->open_cnt) == 0) {
|
||||
v4l2_dbg(1, debug, sd, "%s: current_lens_pos %d, current_related_pos %d\n",
|
||||
__func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos);
|
||||
move_time = dw9800v_move_time(dev_vcm, DW9800V_GRADUAL_MOVELENS_STEPS);
|
||||
while (dac >= DW9800V_GRADUAL_MOVELENS_STEPS) {
|
||||
dw9800v_set_dac(dev_vcm, dac);
|
||||
usleep_range(move_time, move_time + 1000);
|
||||
dac -= DW9800V_GRADUAL_MOVELENS_STEPS;
|
||||
if (dac <= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (dac < DW9800V_GRADUAL_MOVELENS_STEPS) {
|
||||
dac = DW9800V_GRADUAL_MOVELENS_STEPS;
|
||||
dw9800v_set_dac(dev_vcm, dac);
|
||||
if (dac < DW9800V_GRADUAL_MOVELENS_STEPS) {
|
||||
dac = DW9800V_GRADUAL_MOVELENS_STEPS;
|
||||
dw9800v_set_dac(dev_vcm, dac);
|
||||
}
|
||||
/* set to power down mode */
|
||||
dw9800v_write_reg(client, 0x02, 1, 0x01);
|
||||
}
|
||||
/* set to power down mode */
|
||||
dw9800v_write_reg(client, 0x02, 1, 0x01);
|
||||
|
||||
pm_runtime_put(sd->dev);
|
||||
|
||||
@@ -926,6 +932,8 @@ static int dw9800v_probe(struct i2c_client *client,
|
||||
|
||||
dw9800v_dev->vcm_movefull_t =
|
||||
dw9800v_move_time(dw9800v_dev, DW9800V_MAX_REG);
|
||||
atomic_set(&dw9800v_dev->open_cnt, 0);
|
||||
|
||||
pm_runtime_set_active(&client->dev);
|
||||
pm_runtime_enable(&client->dev);
|
||||
pm_runtime_idle(&client->dev);
|
||||
@@ -943,14 +951,12 @@ err_power_off:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dw9800v_remove(struct i2c_client *client)
|
||||
static void dw9800v_remove(struct i2c_client *client)
|
||||
{
|
||||
struct dw9800v_device *dw9800v_dev = i2c_get_clientdata(client);
|
||||
|
||||
pm_runtime_disable(&client->dev);
|
||||
dw9800v_subdev_cleanup(dw9800v_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dw9800v_init(struct i2c_client *client)
|
||||
|
||||
1845
drivers/media/i2c/imx498.c
Normal file
1845
drivers/media/i2c/imx498.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -62,6 +62,12 @@ enum tx_mode_type {
|
||||
DSI_MODE,
|
||||
};
|
||||
|
||||
enum output_color_range {
|
||||
OUT_RANGE_AUTO = 0,
|
||||
OUT_RANGE_LIMIT = 1,
|
||||
OUT_RANGE_FULL = 2,
|
||||
};
|
||||
|
||||
struct rk628_plat_data {
|
||||
int bus_fmt;
|
||||
int tx_mode;
|
||||
@@ -131,6 +137,7 @@ struct rk628_csi {
|
||||
bool is_streaming;
|
||||
bool csi_ints_en;
|
||||
bool dual_mipi_use;
|
||||
int output_range;
|
||||
};
|
||||
|
||||
struct rk628_csi_mode {
|
||||
@@ -771,8 +778,13 @@ static void rk628_dsi_set_scs(struct rk628_csi *csi)
|
||||
|
||||
color_range = rk628_hdmirx_get_range(csi->rk628);
|
||||
rk628_i2c_write(csi->rk628, GRF_CSC_CTRL_CON, SW_YUV2VYU_SWP(0));
|
||||
rk628_post_process_csc_en(csi->rk628,
|
||||
if (csi->output_range == OUT_RANGE_AUTO)
|
||||
rk628_post_process_csc_en(csi->rk628,
|
||||
color_range == HDMIRX_LIMIT_RANGE ? false : true);
|
||||
else if (csi->output_range == OUT_RANGE_LIMIT)
|
||||
rk628_post_process_csc_en(csi->rk628, false);
|
||||
else
|
||||
rk628_post_process_csc_en(csi->rk628, true);
|
||||
}
|
||||
|
||||
/* if avi packet is not stable, reset ctrl*/
|
||||
@@ -1124,8 +1136,13 @@ static void rk628_csi_set_csi(struct v4l2_subdev *sd)
|
||||
|
||||
color_range = rk628_hdmirx_get_range(csi->rk628);
|
||||
rk628_i2c_write(csi->rk628, GRF_CSC_CTRL_CON, SW_YUV2VYU_SWP(1));
|
||||
rk628_post_process_csc_en(csi->rk628,
|
||||
if (csi->output_range == OUT_RANGE_AUTO)
|
||||
rk628_post_process_csc_en(csi->rk628,
|
||||
color_range == HDMIRX_LIMIT_RANGE ? false : true);
|
||||
else if (csi->output_range == OUT_RANGE_LIMIT)
|
||||
rk628_post_process_csc_en(csi->rk628, false);
|
||||
else
|
||||
rk628_post_process_csc_en(csi->rk628, true);
|
||||
}
|
||||
/* if avi packet is not stable, reset ctrl*/
|
||||
if (!avi_rdy) {
|
||||
@@ -1551,11 +1568,9 @@ static void rk628_csi_clear_csi_interrupts(struct v4l2_subdev *sd)
|
||||
rk628_i2c_write(csi->rk628, CSITX1_ERR_INTR_CLR_IMD, 0xffffffff);
|
||||
|
||||
if (csi->rk628->version >= RK628F_VERSION)
|
||||
rk628_i2c_update_bits(csi->rk628, GRF_INTR0_CLR_EN, CSI_INT_EN_MASK |
|
||||
CSI_INT_WRITE_EN_MASK, CSI_INT_EN(3) | CSI_INT_WRITE_EN(3));
|
||||
rk628_i2c_write(csi->rk628, GRF_INTR0_CLR_EN, 0xc000c0);
|
||||
else
|
||||
rk628_i2c_update_bits(csi->rk628, GRF_INTR0_CLR_EN, CSI_INT_EN_MASK |
|
||||
CSI_INT_WRITE_EN_MASK, CSI_INT_EN(1) | CSI_INT_WRITE_EN(1));
|
||||
rk628_i2c_write(csi->rk628, GRF_INTR0_CLR_EN, 0x400040);
|
||||
}
|
||||
|
||||
static void rk628_csi_clear_hdmirx_interrupts(struct v4l2_subdev *sd)
|
||||
@@ -1567,11 +1582,9 @@ static void rk628_csi_clear_hdmirx_interrupts(struct v4l2_subdev *sd)
|
||||
rk628_i2c_write(csi->rk628, HDMI_RX_MD_ICLR, 0xffffffff);
|
||||
rk628_i2c_write(csi->rk628, HDMI_RX_PDEC_ICLR, 0xffffffff);
|
||||
if (csi->rk628->version >= RK628F_VERSION)
|
||||
rk628_i2c_update_bits(csi->rk628, GRF_INTR0_CLR_EN,
|
||||
GRF_INT0_HDMIRX_CLR_MASK_F(1), GRF_INT0_HDMIRX_CLR_F(1));
|
||||
rk628_i2c_write(csi->rk628, GRF_INTR0_CLR_EN, 0x02000200);
|
||||
else
|
||||
rk628_i2c_update_bits(csi->rk628, GRF_INTR0_CLR_EN,
|
||||
GRF_INT0_HDMIRX_CLR_MASK_D(1), GRF_INT0_HDMIRX_CLR_D(1));
|
||||
rk628_i2c_write(csi->rk628, GRF_INTR0_CLR_EN, 0x01000100);
|
||||
}
|
||||
|
||||
static void rk628_csi_error_process(struct v4l2_subdev *sd)
|
||||
@@ -2344,7 +2357,6 @@ static long rk628_csi_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
|
||||
struct rkmodule_capture_info *capture_info;
|
||||
u32 val;
|
||||
u32 stream = 0;
|
||||
bool is_full_range;
|
||||
|
||||
switch (cmd) {
|
||||
case RKMODULE_GET_MODULE_INFO:
|
||||
@@ -2422,8 +2434,8 @@ static long rk628_csi_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
|
||||
*(int *)arg = csi->dsi.vid_mode;
|
||||
break;
|
||||
case RK_HDMIRX_CMD_SET_OUTPUT_RANGE:
|
||||
is_full_range = *((int *)arg);
|
||||
rk628_post_process_csc_en(csi->rk628, is_full_range);
|
||||
csi->output_range = *((int *)arg);
|
||||
v4l2_dbg(1, debug, sd, "set output_range: %d\n", csi->output_range);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOIOCTLCMD;
|
||||
@@ -3048,6 +3060,7 @@ static int rk628_csi_probe_of(struct rk628_csi *csi)
|
||||
csi->nosignal = true;
|
||||
csi->stream_state = 0;
|
||||
csi->avi_rcv_rdy = false;
|
||||
csi->output_range = OUT_RANGE_AUTO;
|
||||
|
||||
ret = 0;
|
||||
|
||||
|
||||
@@ -112,6 +112,18 @@ enum hdmirx_pix_fmt {
|
||||
HDMIRX_YUV420 = 3,
|
||||
};
|
||||
|
||||
enum hdmirx_cn_type {
|
||||
HDMIRX_CN_GRAPHICS = 0,
|
||||
HDMIRX_CN_PHOTO = 1,
|
||||
HDMIRX_CN_CINEMA = 2,
|
||||
HDMIRX_CN_GAME = 3,
|
||||
};
|
||||
|
||||
enum hdmirx_ycc_range {
|
||||
HDMIRX_YCC_LIMIT,
|
||||
HDMIRX_YCC_FULL,
|
||||
};
|
||||
|
||||
static const char * const pix_fmt_str[] = {
|
||||
"RGB888",
|
||||
"YUV422",
|
||||
@@ -372,7 +384,7 @@ static u8 edid_init_data_600M[] = {
|
||||
|
||||
static char *hdmirx_color_space[8] = {
|
||||
"xvYCC601", "xvYCC709", "sYCC601", "Adobe_YCC601",
|
||||
"Adobe_RGB", "BT2020_YcCbcCrc", "BT2020_RGB_OR_YCbCr"
|
||||
"Adobe_RGB", "BT2020_YcCbcCrc", "BT2020_RGB_OR_YCbCr", "RGB"
|
||||
};
|
||||
|
||||
static const struct v4l2_dv_timings_cap hdmirx_timings_cap = {
|
||||
@@ -771,7 +783,7 @@ try_loop:
|
||||
|
||||
static void hdmirx_get_color_space(struct rk_hdmirx_dev *hdmirx_dev)
|
||||
{
|
||||
u32 val;
|
||||
u32 val, EC2_0, C1_C0;
|
||||
struct v4l2_device *v4l2_dev = &hdmirx_dev->v4l2_dev;
|
||||
|
||||
/*
|
||||
@@ -781,16 +793,58 @@ static void hdmirx_get_color_space(struct rk_hdmirx_dev *hdmirx_dev)
|
||||
*/
|
||||
hdmirx_readl(hdmirx_dev, PKTDEC_AVIIF_PH2_1);
|
||||
val = hdmirx_readl(hdmirx_dev, PKTDEC_AVIIF_PB3_0);
|
||||
hdmirx_dev->cur_color_space = (val & EXTEND_COLORIMETRY) >> 28;
|
||||
EC2_0 = (val & EXTEND_COLORIMETRY) >> 20;
|
||||
C1_C0 = (val & COLORIMETRY_MASK) >> 14;
|
||||
if (hdmirx_dev->pix_fmt == HDMIRX_RGB888) {
|
||||
if (EC2_0 == HDMIRX_ADOBE_RGB ||
|
||||
EC2_0 == HDMIRX_BT2020_RGB_OR_YCC)
|
||||
hdmirx_dev->cur_color_space = EC2_0;
|
||||
else
|
||||
hdmirx_dev->cur_color_space = HDMIRX_RGB;
|
||||
} else {
|
||||
switch (C1_C0) {
|
||||
case 0:
|
||||
hdmirx_dev->cur_color_space = HDMIRX_XVYCC709;
|
||||
break;
|
||||
case 1:
|
||||
hdmirx_dev->cur_color_space = HDMIRX_XVYCC601;
|
||||
break;
|
||||
case 2:
|
||||
hdmirx_dev->cur_color_space = HDMIRX_XVYCC709;
|
||||
break;
|
||||
default:
|
||||
hdmirx_dev->cur_color_space = EC2_0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
v4l2_dbg(2, debug, v4l2_dev, "%s: video standard: %s\n", __func__,
|
||||
hdmirx_color_space[hdmirx_dev->cur_color_space]);
|
||||
}
|
||||
|
||||
static bool IsColorRangeLimitFormat(uint32_t width, uint32_t height, bool interlace)
|
||||
{
|
||||
if (((width == 720) && (height == 240) && (interlace == false)) \
|
||||
|| ((width == 720) && (height == 1201) && (interlace == false)) \
|
||||
|| ((width == 720) && (height == 480) && (interlace == true)) \
|
||||
|| ((width == 720) && (height == 576) && (interlace == true)) \
|
||||
|| ((width == 1440) && (height == 480) && (interlace == true)) \
|
||||
|| ((width == 1440) && (height == 576) && (interlace == true)) \
|
||||
|| ((width == 1920) && (height == 1080) && (interlace == true)) \
|
||||
|| ((width == 2880) && (height == 480) && (interlace == true)) \
|
||||
|| ((width == 3840) && (height == 2160) && (interlace == false))) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void hdmirx_get_color_range(struct rk_hdmirx_dev *hdmirx_dev)
|
||||
{
|
||||
u32 val;
|
||||
int color_range;
|
||||
int rgb_range, yuv_range, cn_type;
|
||||
struct v4l2_dv_timings timings = hdmirx_dev->timings;
|
||||
struct v4l2_bt_timings *bt = &timings.bt;
|
||||
struct v4l2_device *v4l2_dev = &hdmirx_dev->v4l2_dev;
|
||||
|
||||
/*
|
||||
@@ -800,16 +854,36 @@ static void hdmirx_get_color_range(struct rk_hdmirx_dev *hdmirx_dev)
|
||||
*/
|
||||
hdmirx_readl(hdmirx_dev, PKTDEC_AVIIF_PH2_1);
|
||||
val = hdmirx_readl(hdmirx_dev, PKTDEC_AVIIF_PB3_0);
|
||||
color_range = (val & RGB_QUANTIZATION_RANGE) >> 26;
|
||||
|
||||
/* byte3 bit[3:2]*/
|
||||
rgb_range = (val & RGB_QUANTIZATION_RANGE) >> 26;
|
||||
val = hdmirx_readl(hdmirx_dev, PKTDEC_AVIIF_PB7_4);
|
||||
/* byte5 bit[7:6]*/
|
||||
yuv_range = (val & YUV_QUANTIZATION_RANGE) >> 14;
|
||||
/* byte5 bit[5:4]*/
|
||||
cn_type = (val & CN_TYPE_MASK) >> 12;
|
||||
if (hdmirx_dev->pix_fmt != HDMIRX_RGB888) {
|
||||
hdmirx_dev->cur_color_range = color_range;
|
||||
if (yuv_range == HDMIRX_YCC_LIMIT)
|
||||
hdmirx_dev->cur_color_range = HDMIRX_LIMIT_RANGE;
|
||||
else if (yuv_range == HDMIRX_YCC_FULL)
|
||||
hdmirx_dev->cur_color_range = HDMIRX_FULL_RANGE;
|
||||
else
|
||||
hdmirx_dev->cur_color_range = HDMIRX_DEFAULT_RANGE;
|
||||
} else {
|
||||
if (color_range != HDMIRX_DEFAULT_RANGE) {
|
||||
hdmirx_dev->cur_color_range = color_range;
|
||||
if (rgb_range != HDMIRX_DEFAULT_RANGE) {
|
||||
(hdmirx_dev->is_dvi_mode) ?
|
||||
(hdmirx_dev->cur_color_range = HDMIRX_FULL_RANGE) :
|
||||
(hdmirx_dev->cur_color_range = rgb_range);
|
||||
} else {
|
||||
(hdmirx_dev->cur_vic) ?
|
||||
(hdmirx_dev->cur_color_range = HDMIRX_LIMIT_RANGE) :
|
||||
(hdmirx_dev->cur_color_range = HDMIRX_FULL_RANGE);
|
||||
if (cn_type == HDMIRX_CN_GRAPHICS) {
|
||||
hdmirx_dev->cur_color_range = HDMIRX_FULL_RANGE;
|
||||
} else {
|
||||
if (IsColorRangeLimitFormat(bt->width,
|
||||
bt->height, bt->interlaced))
|
||||
hdmirx_dev->cur_color_range = HDMIRX_LIMIT_RANGE;
|
||||
else
|
||||
hdmirx_dev->cur_color_range = HDMIRX_FULL_RANGE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -259,10 +259,13 @@
|
||||
#define PKTDEC_ACR_PB7_4 0x1108
|
||||
#define PKTDEC_AVIIF_PH2_1 0x1200
|
||||
#define PKTDEC_AVIIF_PB3_0 0x1204
|
||||
#define COLORIMETRY_MASK GENMASK(23, 22)
|
||||
#define RGB_QUANTIZATION_RANGE GENMASK(27, 26)
|
||||
#define EXTEND_COLORIMETRY GENMASK(30, 28)
|
||||
#define PKTDEC_AVIIF_PB7_4 0x1208
|
||||
#define VIC_VAL_MASK GENMASK(6, 0)
|
||||
#define CN_TYPE_MASK GENMASK(13, 12)
|
||||
#define YUV_QUANTIZATION_RANGE GENMASK(15, 14)
|
||||
#define PKTDEC_AVIIF_PB11_8 0x120c
|
||||
#define PKTDEC_AVIIF_PB15_12 0x1210
|
||||
#define PKTDEC_AVIIF_PB19_16 0x1214
|
||||
|
||||
@@ -561,16 +561,9 @@ static int ufs_rockchip_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct ufs_hba *hba = dev_get_drvdata(dev);
|
||||
struct ufs_rockchip_host *host = ufshcd_get_variant(hba);
|
||||
int ret = 0;
|
||||
|
||||
ret = ufshcd_runtime_suspend(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
clk_disable_unprepare(host->ref_out_clk);
|
||||
ufs_rockchip_restore_link(hba, true);
|
||||
|
||||
return 0;
|
||||
return ufs_rockchip_restore_link(hba, true);
|
||||
}
|
||||
|
||||
static int ufs_rockchip_runtime_resume(struct device *dev)
|
||||
@@ -589,9 +582,7 @@ static int ufs_rockchip_runtime_resume(struct device *dev)
|
||||
udelay(1);
|
||||
reset_control_deassert(host->rst);
|
||||
|
||||
ufs_rockchip_restore_link(hba, false);
|
||||
|
||||
return ufshcd_runtime_resume(dev);
|
||||
return ufs_rockchip_restore_link(hba, false);
|
||||
}
|
||||
|
||||
static int ufs_rockchip_suspend(struct device *dev)
|
||||
@@ -603,7 +594,7 @@ static int ufs_rockchip_suspend(struct device *dev)
|
||||
|
||||
ufs_rockchip_restore_link(hba, true);
|
||||
|
||||
return ufshcd_system_suspend(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ufs_rockchip_resume(struct device *dev)
|
||||
@@ -617,7 +608,7 @@ static int ufs_rockchip_resume(struct device *dev)
|
||||
ufs_rockchip_device_reset(hba);
|
||||
ufs_rockchip_restore_link(hba, false);
|
||||
|
||||
return ufshcd_system_resume(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops ufs_rockchip_pm_ops = {
|
||||
|
||||
@@ -1877,7 +1877,7 @@ static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool int
|
||||
if (!DWC3_IP_IS(DWC3) || DWC3_VER_IS_PRIOR(DWC3, 310A))
|
||||
mdelay(1);
|
||||
dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
|
||||
} else if (!ret) {
|
||||
} else {
|
||||
dep->flags |= DWC3_EP_END_TRANSFER_PENDING;
|
||||
}
|
||||
|
||||
@@ -2254,6 +2254,8 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
|
||||
|
||||
list_for_each_entry(r, &dep->started_list, list) {
|
||||
if (r == req) {
|
||||
struct dwc3_request *t;
|
||||
|
||||
/* wait until it is processed */
|
||||
dwc3_stop_active_transfer(dep, true, true);
|
||||
|
||||
@@ -2261,7 +2263,10 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
|
||||
* Remove any started request if the transfer is
|
||||
* cancelled.
|
||||
*/
|
||||
dwc3_gadget_move_cancelled_request(r, DWC3_REQUEST_STATUS_DEQUEUED);
|
||||
list_for_each_entry_safe(r, t, &dep->started_list, list) {
|
||||
dwc3_gadget_move_cancelled_request(r,
|
||||
DWC3_REQUEST_STATUS_DEQUEUED);
|
||||
}
|
||||
|
||||
dep->flags &= ~DWC3_EP_WAIT_TRANSFER_COMPLETE;
|
||||
|
||||
|
||||
@@ -172,6 +172,39 @@ done:
|
||||
static irqreturn_t husb311_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct husb311_chip *chip = dev_id;
|
||||
enum typec_cc_status cc1, cc2;
|
||||
u8 reg, role_ctrl;
|
||||
u8 status;
|
||||
|
||||
husb311_read8(chip, TCPC_ALERT, &status);
|
||||
dev_dbg(chip->dev, "status 0x%02x", status);
|
||||
|
||||
/*
|
||||
* If husb311 detects one of CC is Rp, let do clear the another CC
|
||||
* status in anyway to dodge the non-standard cables that double Rp
|
||||
* connected to VBUS which produced by Huawei and etc.
|
||||
*/
|
||||
if (status & TCPC_ALERT_CC_STATUS) {
|
||||
husb311_read8(chip, TCPC_ROLE_CTRL, &role_ctrl);
|
||||
husb311_read8(chip, TCPC_CC_STATUS, ®);
|
||||
cc1 = tcpci_to_typec_cc((reg >> TCPC_CC_STATUS_CC1_SHIFT) &
|
||||
TCPC_CC_STATUS_CC1_MASK,
|
||||
reg & TCPC_CC_STATUS_TERM ||
|
||||
tcpc_presenting_rd(role_ctrl, CC1));
|
||||
cc2 = tcpci_to_typec_cc((reg >> TCPC_CC_STATUS_CC2_SHIFT) &
|
||||
TCPC_CC_STATUS_CC2_MASK,
|
||||
reg & TCPC_CC_STATUS_TERM ||
|
||||
tcpc_presenting_rd(role_ctrl, CC2));
|
||||
|
||||
dev_dbg(chip->dev, "CC1 %u, CC2 %u", cc1, cc2);
|
||||
if (cc1 == TYPEC_CC_RP_DEF) {
|
||||
role_ctrl |= TCPC_ROLE_CTRL_CC_OPEN << TCPC_ROLE_CTRL_CC2_SHIFT;
|
||||
husb311_write8(chip, TCPC_ROLE_CTRL, role_ctrl);
|
||||
} else if (cc2 == TYPEC_CC_RP_DEF) {
|
||||
role_ctrl |= TCPC_ROLE_CTRL_CC_OPEN << TCPC_ROLE_CTRL_CC1_SHIFT;
|
||||
husb311_write8(chip, TCPC_ROLE_CTRL, role_ctrl);
|
||||
}
|
||||
}
|
||||
|
||||
return tcpci_irq(chip->tcpci);
|
||||
}
|
||||
|
||||
74
include/linux/rockchip-panel-notifier.h
Normal file
74
include/linux/rockchip-panel-notifier.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2024 Rockchip Electronics Co. Ltd.
|
||||
* Author: Zhibin Huang <zhibin.huang@rock-chips.com>
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_ROCKCHIP_PANEL_NOTIFIER_H__
|
||||
#define __LINUX_ROCKCHIP_PANEL_NOTIFIER_H__
|
||||
|
||||
#include <linux/of.h>
|
||||
#include <linux/notifier.h>
|
||||
|
||||
struct rockchip_panel_notifier {
|
||||
struct list_head list;
|
||||
struct drm_panel *panel;
|
||||
struct blocking_notifier_head nh;
|
||||
};
|
||||
|
||||
enum rockchip_panel_event {
|
||||
PANEL_PRE_ENABLE,
|
||||
PANEL_ENABLED,
|
||||
PANEL_PRE_DISABLE,
|
||||
PANEL_DISABLED,
|
||||
};
|
||||
|
||||
struct rockchip_panel_edata {
|
||||
void *data;
|
||||
};
|
||||
|
||||
#if IS_REACHABLE(CONFIG_ROCKCHIP_PANEL_NOTIFIER)
|
||||
int devm_rockchip_panel_notifier_register(struct device *dev,
|
||||
struct drm_panel *panel,
|
||||
struct rockchip_panel_notifier *pn);
|
||||
void devm_rockchip_panel_notifier_unregister(struct device *dev);
|
||||
int rockchip_panel_notifier_call_chain(struct rockchip_panel_notifier *pn,
|
||||
enum rockchip_panel_event panel_event,
|
||||
struct rockchip_panel_edata *panel_edata);
|
||||
int devm_rockchip_panel_notifier_register_client(struct device *dev, struct notifier_block *nb);
|
||||
void devm_rockchip_panel_notifier_unregister_client(struct device *dev);
|
||||
#else
|
||||
static inline int
|
||||
devm_rockchip_panel_notifier_register(struct device *dev,
|
||||
struct drm_panel *panel,
|
||||
struct rockchip_panel_notifier *pn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void devm_rockchip_panel_notifier_unregister(struct device *dev)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int
|
||||
rockchip_panel_notifier_call_chain(struct rockchip_panel_notifier *pn,
|
||||
enum rockchip_panel_event panel_event,
|
||||
struct rockchip_panel_edata *panel_edata)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
devm_rockchip_panel_notifier_register_client(struct device *dev,
|
||||
struct notifier_block *nb)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
devm_rockchip_panel_notifier_unregister_client(struct device *dev)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_ROCKCHIP_PANEL_NOTIFIER */
|
||||
|
||||
#endif /* __LINUX_ROCKCHIP_PANEL_NOTIFIER_H__ */
|
||||
Reference in New Issue
Block a user