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:
Tao Huang
2024-04-19 17:36:53 +08:00
28 changed files with 2641 additions and 334 deletions

View File

@@ -504,7 +504,7 @@
};
&route_hdmi {
status = "disabled";
status = "okay";
connect = <&vp0_out_hdmi>;
};

View File

@@ -408,7 +408,7 @@
};
&route_hdmi {
status = "disabled";
status = "okay";
connect = <&vp0_out_hdmi>;
};

View File

@@ -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>;
};
};

View File

@@ -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);

View File

@@ -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

View File

@@ -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/

View File

@@ -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

View File

@@ -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)

View 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(&notifier_list_lock);
list_for_each_entry(pn, &notifier_list, list) {
if (pn->panel == panel)
goto find;
}
pn = NULL;
find:
mutex_unlock(&notifier_list_lock);
if (!pn)
return -ENODEV;
ret = blocking_notifier_chain_register(&pn->nh, this->nb);
if (ret)
return ret;
this->pn = pn;
mutex_lock(&notifier_client_list_lock);
list_add_tail(&this->list, &notifier_client_list);
mutex_unlock(&notifier_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(&notifier_client_list_lock);
list_for_each_entry_safe(pn_client, next, &notifier_client_list, list) {
if (pn_client != client)
continue;
rockchip_panel_notifier_unregister_client(pn_client);
list_del_init(&pn_client->list);
}
mutex_unlock(&notifier_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(&notifier_list_lock);
list_add_tail(&pn->list, &notifier_list);
mutex_unlock(&notifier_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(&notifier_client_list_lock);
list_for_each_entry_safe(pn_client, next, &notifier_client_list, list) {
if (pn_client->pn != pn)
continue;
rockchip_panel_notifier_unregister_client(pn_client);
list_del_init(&pn_client->list);
}
mutex_unlock(&notifier_client_list_lock);
mutex_lock(&notifier_list_lock);
list_del_init(&pn->list);
mutex_unlock(&notifier_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");

View File

@@ -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.

View File

@@ -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

View File

@@ -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)

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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;

View File

@@ -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;
}
}
}

View File

@@ -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

View File

@@ -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 = {

View File

@@ -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;

View File

@@ -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, &reg);
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);
}

View 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__ */