mirror of https://github.com/armbian/build.git
3541 lines
113 KiB
Diff
3541 lines
113 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Patrick Yavitz <pyavitz@armbian.com>
|
|
Date: Sat, 22 Jun 2024 08:49:36 -0400
|
|
Subject: update to v1.0.3
|
|
|
|
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
|
|
---
|
|
Makefile | 6 +-
|
|
drivers/clk/spacemit/ccu-spacemit-k1x.c | 4 +-
|
|
drivers/gpu/drm/img-rogue/rgxtimecorr.c | 2 +-
|
|
drivers/gpu/drm/spacemit/Kconfig | 16 +-
|
|
drivers/gpu/drm/spacemit/Makefile | 2 +
|
|
drivers/gpu/drm/spacemit/dphy/spacemit_dphy_drv.c | 6 +-
|
|
drivers/gpu/drm/spacemit/dpu/dpu_saturn.c | 10 +-
|
|
drivers/gpu/drm/spacemit/lt8911exb.c | 236 +--
|
|
drivers/gpu/drm/spacemit/lt9711.c | 406 ++++
|
|
drivers/gpu/drm/spacemit/spacemit_dsi.c | 8 +-
|
|
drivers/gpu/drm/spacemit/spacemit_hdmi.c | 39 +-
|
|
drivers/pci/controller/dwc/pcie-k1x.c | 57 +-
|
|
drivers/regulator/spacemit-regulator.c | 27 +-
|
|
drivers/remoteproc/k1x-rproc.c | 9 +-
|
|
drivers/soc/spacemit/jpu/jpu.c | 4 +-
|
|
drivers/soc/spacemit/pm_domain/k1x-pm_domain.c | 3 +-
|
|
drivers/spi/spi-k1x-qspi.c | 5 +-
|
|
drivers/target/target_core_configfs.c | 20 +
|
|
drivers/target/target_core_spc.c | 920 ++++++++++
|
|
drivers/tty/serial/pxa_k1x.c | 4 +-
|
|
drivers/usb/gadget/function/f_tcm.c | 26 +-
|
|
drivers/usb/gadget/function/tcm.h | 1 +
|
|
include/linux/mfd/spacemit/spacemit_pmic.h | 1 +
|
|
include/linux/mfd/spacemit/spm8821.h | 5 +-
|
|
include/scsi/scsi_proto.h | 10 +
|
|
include/target/target_core_base.h | 18 +
|
|
init/version-timestamp.c | 2 +-
|
|
sound/soc/codecs/es8316.c | 28 +
|
|
sound/soc/codecs/es8326.c | 116 +-
|
|
sound/soc/spacemit/spacemit-snd-card.c | 55 +
|
|
sound/soc/spacemit/spacemit-snd-i2s.c | 41 +-
|
|
sound/soc/spacemit/spacemit-snd-pcm-dma.c | 12 +-
|
|
sound/soc/spacemit/spacemit-snd-sspa.c | 2 +-
|
|
33 files changed, 1848 insertions(+), 253 deletions(-)
|
|
|
|
diff --git a/Makefile b/Makefile
|
|
index 111111111111..222222222222 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -377,8 +377,9 @@ include $(srctree)/scripts/Kbuild.include
|
|
|
|
# Read KERNELRELEASE from include/config/kernel.release (if it exists)
|
|
KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
|
|
+KERNELGITVER = $(shell git rev-parse --short HEAD)
|
|
KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
|
|
-export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
|
|
+export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION KERNELGITVER
|
|
|
|
include $(srctree)/scripts/subarch.include
|
|
|
|
@@ -1332,7 +1333,8 @@ define filechk_version.h
|
|
((c) > 255 ? 255 : (c)))'; \
|
|
echo \#define LINUX_VERSION_MAJOR $(VERSION); \
|
|
echo \#define LINUX_VERSION_PATCHLEVEL $(PATCHLEVEL); \
|
|
- echo \#define LINUX_VERSION_SUBLEVEL $(SUBLEVEL)
|
|
+ echo \#define LINUX_VERSION_SUBLEVEL $(SUBLEVEL); \
|
|
+ echo \#define LINUX_VERSION_COMMITID \"$(KERNELGITVER)\"
|
|
endef
|
|
|
|
$(version_h): PATCHLEVEL := $(or $(PATCHLEVEL), 0)
|
|
diff --git a/drivers/clk/spacemit/ccu-spacemit-k1x.c b/drivers/clk/spacemit/ccu-spacemit-k1x.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/clk/spacemit/ccu-spacemit-k1x.c
|
|
+++ b/drivers/clk/spacemit/ccu-spacemit-k1x.c
|
|
@@ -643,10 +643,10 @@ static SPACEMIT_CCU_GATE_NO_PARENT(onewire_clk, "onewire_clk", NULL,
|
|
BASE_TYPE_APBC, APBC_ONEWIRE_CLK_RST,
|
|
0x3, 0x3, 0x0, 0);
|
|
|
|
-static SPACEMIT_CCU_GATE_FACTOR(i2s_sysclk, "i2s_sysclk", "pll1_d16_153p6",
|
|
+static SPACEMIT_CCU_GATE_FACTOR(i2s_sysclk, "i2s_sysclk", "pll1_d8_307p2",
|
|
BASE_TYPE_MPMU, MPMU_ISCCR,
|
|
BIT(31), BIT(31), 0x0,
|
|
- 50, 1, 0);
|
|
+ 200, 1, 0);
|
|
static SPACEMIT_CCU_GATE_FACTOR(i2s_bclk, "i2s_bclk", "i2s_sysclk",
|
|
BASE_TYPE_MPMU, MPMU_ISCCR,
|
|
BIT(29), BIT(29), 0x0,
|
|
diff --git a/drivers/gpu/drm/img-rogue/rgxtimecorr.c b/drivers/gpu/drm/img-rogue/rgxtimecorr.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/gpu/drm/img-rogue/rgxtimecorr.c
|
|
+++ b/drivers/gpu/drm/img-rogue/rgxtimecorr.c
|
|
@@ -428,7 +428,7 @@ static inline IMG_UINT32 _RGXGPUFreqGetIndex(RGX_GPU_DVFS_TABLE *psGpuDVFSTable,
|
|
|
|
i--;
|
|
|
|
- PVR_DPF((PVR_DBG_ERROR, "GPU frequency table in the driver is full! "
|
|
+ PVR_DPF((PVR_DBG_WARNING, "GPU frequency table in the driver is full! "
|
|
"Table size should be increased! Overriding last entry (%u) with %u",
|
|
paui32GPUFrequencies[i], ui32CoreClockSpeed));
|
|
|
|
diff --git a/drivers/gpu/drm/spacemit/Kconfig b/drivers/gpu/drm/spacemit/Kconfig
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/gpu/drm/spacemit/Kconfig
|
|
+++ b/drivers/gpu/drm/spacemit/Kconfig
|
|
@@ -33,4 +33,18 @@ config DRM_LT8911EXB
|
|
select DRM_DP_AUX_BUS
|
|
|
|
help
|
|
- Support for Lontium LT8911EXB DSI to eDP driver.
|
|
\ No newline at end of file
|
|
+ Support for Lontium LT8911EXB DSI to eDP driver.
|
|
+
|
|
+config DRM_LT9711
|
|
+ tristate "Lontium LT9711 DSI to DP"
|
|
+ default y
|
|
+ depends on DRM_SPACEMIT
|
|
+ select DRM_KMS_HELPER
|
|
+ select REGMAP_I2C
|
|
+ select DRM_PANEL
|
|
+ select DRM_MIPI_DSI
|
|
+ select AUXILIARY_BUS
|
|
+ select DRM_DP_AUX_BUS
|
|
+
|
|
+ help
|
|
+ Support for Lontium LT9711 DSI to eDP driver.
|
|
diff --git a/drivers/gpu/drm/spacemit/Makefile b/drivers/gpu/drm/spacemit/Makefile
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/gpu/drm/spacemit/Makefile
|
|
+++ b/drivers/gpu/drm/spacemit/Makefile
|
|
@@ -29,4 +29,6 @@ obj-$(CONFIG_DRM_SPACEMIT) += spacemit-drm.o
|
|
|
|
obj-$(CONFIG_DRM_LT8911EXB) += lt8911exb.o
|
|
|
|
+obj-$(CONFIG_DRM_LT9711) += lt9711.o
|
|
+
|
|
obj-$(CONFIG_SPACEMIT_MIPI_PANEL) += spacemit_mipi_panel.o
|
|
diff --git a/drivers/gpu/drm/spacemit/dphy/spacemit_dphy_drv.c b/drivers/gpu/drm/spacemit/dphy/spacemit_dphy_drv.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/gpu/drm/spacemit/dphy/spacemit_dphy_drv.c
|
|
+++ b/drivers/gpu/drm/spacemit/dphy/spacemit_dphy_drv.c
|
|
@@ -211,7 +211,7 @@ static void dphy_set_timing(struct spacemit_dphy_ctx *dphy_ctx)
|
|
| (ta_go << CFG_DPHY_TIME_TA_GO_SHIFT)
|
|
| (wakeup << CFG_DPHY_TIME_WAKEUP_SHIFT);
|
|
|
|
- DRM_INFO("%s dphy time1 ta_get %d ta_go %d wakeup %d reg 0x%x\n", __func__, ta_get, ta_go, wakeup, reg);
|
|
+ DRM_DEBUG("%s dphy time1 ta_get %d ta_go %d wakeup %d reg 0x%x\n", __func__, ta_get, ta_go, wakeup, reg);
|
|
#ifdef DPTC_DPHY_TEST
|
|
dptc_dsi_write(0x44, 0x0403001F);
|
|
#else
|
|
@@ -223,7 +223,7 @@ static void dphy_set_timing(struct spacemit_dphy_ctx *dphy_ctx)
|
|
| (ck_zero << CFG_DPHY_TIME_CLK_ZERO_SHIFT)
|
|
| (lpx_clk << CFG_DPHY_TIME_CLK_LPX_SHIFT);
|
|
|
|
- DRM_INFO("%s dphy time2 ck_exit %d ck_trail %d ck_zero %d lpx_clk %d reg 0x%x\n", __func__, ck_exit, ck_trail, ck_zero, lpx_clk, reg);
|
|
+ DRM_DEBUG("%s dphy time2 ck_exit %d ck_trail %d ck_zero %d lpx_clk %d reg 0x%x\n", __func__, ck_exit, ck_trail, ck_zero, lpx_clk, reg);
|
|
#ifdef DPTC_DPHY_TEST
|
|
dptc_dsi_write(0x48, 0x02010500);
|
|
#else
|
|
@@ -234,7 +234,7 @@ static void dphy_set_timing(struct spacemit_dphy_ctx *dphy_ctx)
|
|
reg = (lpx_clk << CFG_DPHY_TIME_LPX_SHIFT)
|
|
| phy_timing->req_ready << CFG_DPHY_TIME_REQRDY_SHIFT;
|
|
|
|
- DRM_INFO("%s dphy time3 lpx_clk %d req_ready %d reg 0x%x\n", __func__, lpx_clk, phy_timing->req_ready, reg);
|
|
+ DRM_DEBUG("%s dphy time3 lpx_clk %d req_ready %d reg 0x%x\n", __func__, lpx_clk, phy_timing->req_ready, reg);
|
|
#ifdef DPTC_DPHY_TEST
|
|
dptc_dsi_write(0x4c, 0x001F);
|
|
#else
|
|
diff --git a/drivers/gpu/drm/spacemit/dpu/dpu_saturn.c b/drivers/gpu/drm/spacemit/dpu/dpu_saturn.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/gpu/drm/spacemit/dpu/dpu_saturn.c
|
|
+++ b/drivers/gpu/drm/spacemit/dpu/dpu_saturn.c
|
|
@@ -643,15 +643,15 @@ static int dpu_enable_clocks(struct spacemit_dpu *dpu)
|
|
}
|
|
|
|
clk_val = clk_get_rate(clk_ctx->pxclk);
|
|
- DRM_INFO("get pxclk=%lld\n", clk_val);
|
|
+ DRM_DEBUG("get pxclk=%lld\n", clk_val);
|
|
clk_val = clk_get_rate(clk_ctx->mclk);
|
|
- DRM_INFO("get mclk=%lld\n", clk_val);
|
|
+ DRM_DEBUG("get mclk=%lld\n", clk_val);
|
|
clk_val = clk_get_rate(clk_ctx->hclk);
|
|
- DRM_INFO("get hclk=%lld\n", clk_val);
|
|
+ DRM_DEBUG("get hclk=%lld\n", clk_val);
|
|
clk_val = clk_get_rate(clk_ctx->escclk);
|
|
- DRM_INFO("get escclk=%lld\n", clk_val);
|
|
+ DRM_DEBUG("get escclk=%lld\n", clk_val);
|
|
clk_val = clk_get_rate(clk_ctx->bitclk);
|
|
- DRM_INFO("get bitclk=%lld\n", clk_val);
|
|
+ DRM_DEBUG("get bitclk=%lld\n", clk_val);
|
|
|
|
udelay(10);
|
|
}
|
|
diff --git a/drivers/gpu/drm/spacemit/lt8911exb.c b/drivers/gpu/drm/spacemit/lt8911exb.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/gpu/drm/spacemit/lt8911exb.c
|
|
+++ b/drivers/gpu/drm/spacemit/lt8911exb.c
|
|
@@ -18,12 +18,9 @@
|
|
#include <linux/regmap.h>
|
|
#include <linux/regulator/consumer.h>
|
|
#include <linux/media-bus-format.h>
|
|
-
|
|
#include <linux/atomic.h>
|
|
#include <linux/workqueue.h>
|
|
-
|
|
#include <asm/unaligned.h>
|
|
-
|
|
#include <drm/drm_atomic.h>
|
|
#include <drm/drm_atomic_helper.h>
|
|
#include <drm/drm_bridge.h>
|
|
@@ -41,12 +38,12 @@
|
|
#define EDID_SEG_SIZE 256
|
|
#define EDID_LEN 16
|
|
|
|
-// #define _Test_Pattern_
|
|
-
|
|
#define MIPI_DSI_1920x1080 1
|
|
#define MIPI_DSI_1920x1200 0
|
|
|
|
-#define _uart_debug_
|
|
+// #define _test_pattern_
|
|
+// #define _read_edid_
|
|
+// #define _uart_debug_
|
|
#define _eDP_2G7_
|
|
#define _link_train_enable_
|
|
|
|
@@ -72,13 +69,13 @@ static int Nvid_Val[] = {0x0080, 0x0800};
|
|
static int MIPI_Timing[] =
|
|
// hfp, hs, hbp, hact, htotal, vfp, vs, vbp, vact, vtotal, pixel_CLK/10000
|
|
|
|
-//1920x1080
|
|
+// 1920x1080
|
|
#if MIPI_DSI_1920x1080
|
|
// {48, 32, 200, 1920, 2200, 3, 6, 31, 1080, 1120, 14784}; // boe config for linux
|
|
{48, 32, 200, 1920, 2200, 3, 6, 31, 1080, 1120, 14285}; // boe config for linux
|
|
#endif
|
|
|
|
-//1920x1200
|
|
+// 1920x1200
|
|
#if MIPI_DSI_1920x1200
|
|
// {16, 16, 298, 1920, 2250, 3, 14, 19, 1200, 1236, 16684}; // boe config for linux
|
|
{16, 16, 298, 1920, 2250, 3, 14, 19, 1200, 1236, 15360}; // boe config for linux
|
|
@@ -108,7 +105,7 @@ bool EDID_Reply = 0;
|
|
bool ScrambleMode = 0;
|
|
|
|
static const struct drm_display_mode lt8911exb_panel_modes[] = {
|
|
-//1920x1080
|
|
+// 1920x1080
|
|
#if MIPI_DSI_1920x1080
|
|
{
|
|
.clock = 142857143 / 1000,
|
|
@@ -141,7 +138,6 @@ static const struct drm_display_mode lt8911exb_panel_modes[] = {
|
|
|
|
};
|
|
|
|
-
|
|
enum
|
|
{
|
|
_Level0_ = 0, // 27.8 mA 0x83/0x00
|
|
@@ -151,12 +147,12 @@ enum
|
|
_Level4_, // 21.4 mA 0x82/0x80
|
|
_Level5_, // 18.2 mA 0x82/0x40
|
|
_Level6_, // 16.6 mA 0x82/0x20
|
|
- _Level7_, // 15mA 0x82/0x00 // level 1
|
|
+ _Level7_, // 15 mA 0x82/0x00 // level 1
|
|
_Level8_, // 12.8mA 0x81/0x00 // level 2
|
|
_Level9_, // 11.2mA 0x80/0xe0 // level 3
|
|
_Level10_, // 9.6mA 0x80/0xc0 // level 4
|
|
- _Level11_, // 8mA 0x80/0xa0 // level 5
|
|
- _Level12_, // 6mA 0x80/0x80 // level 6
|
|
+ _Level11_, // 8mA 0x80/0xa0 // level 5
|
|
+ _Level12_, // 6mA 0x80/0x80 // level 6
|
|
};
|
|
|
|
u8 Swing_Setting1[] = {0x83, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x81, 0x80, 0x80, 0x80, 0x80};
|
|
@@ -176,12 +172,10 @@ struct lt8911exb {
|
|
struct mipi_dsi_device *dsi0;
|
|
struct mipi_dsi_device *dsi1;
|
|
|
|
- //bool ac_mode;
|
|
- struct gpio_desc *reset_gpio; //reset
|
|
- struct gpio_desc *enable_gpio; //power
|
|
- struct gpio_desc *standby_gpio; //standby
|
|
-
|
|
- struct gpio_desc *bl_gpio; //backlight
|
|
+ struct gpio_desc *reset_gpio; //reset
|
|
+ struct gpio_desc *enable_gpio; //power
|
|
+ struct gpio_desc *standby_gpio; //standby
|
|
+ struct gpio_desc *bl_gpio; //backlight
|
|
|
|
bool power_on;
|
|
bool sleep;
|
|
@@ -201,25 +195,20 @@ struct lt8911exb {
|
|
bool init_work_pending;
|
|
};
|
|
|
|
-
|
|
static const struct regmap_config lt8911exb_regmap_config = {
|
|
.reg_bits = 8,
|
|
.val_bits = 8,
|
|
.max_register = 0xff,
|
|
};
|
|
|
|
-
|
|
static struct lt8911exb *panel_to_lt8911exb(struct drm_panel *panel)
|
|
{
|
|
return container_of(panel, struct lt8911exb, base);
|
|
}
|
|
|
|
-
|
|
-//--------------------------------------enable function-------------------------------//
|
|
-
|
|
void lt8911exb_mipi_video_timing(struct lt8911exb *lt8911exb)
|
|
{
|
|
- unsigned int tmp;
|
|
+ __maybe_unused unsigned int tmp;
|
|
|
|
regmap_write(lt8911exb->regmap, 0xff, 0xd0);
|
|
regmap_write(lt8911exb->regmap, 0x0d, (MIPI_Timing[vtotal] / 256));
|
|
@@ -230,14 +219,14 @@ void lt8911exb_mipi_video_timing(struct lt8911exb *lt8911exb)
|
|
regmap_write(lt8911exb->regmap, 0x12, (MIPI_Timing[htotal] % 256)); //htotal
|
|
regmap_write(lt8911exb->regmap, 0x13, (MIPI_Timing[hact] / 256));
|
|
regmap_write(lt8911exb->regmap, 0x14, (MIPI_Timing[hact] % 256)); //hactive
|
|
- regmap_write(lt8911exb->regmap, 0x15, (MIPI_Timing[vs] % 256)); //vsa
|
|
- regmap_write(lt8911exb->regmap, 0x16, (MIPI_Timing[hs] % 256)); //hsa
|
|
+ regmap_write(lt8911exb->regmap, 0x15, (MIPI_Timing[vs] % 256)); //vsa
|
|
+ regmap_write(lt8911exb->regmap, 0x16, (MIPI_Timing[hs] % 256)); //hsa
|
|
regmap_write(lt8911exb->regmap, 0x17, (MIPI_Timing[vfp] / 256));
|
|
regmap_write(lt8911exb->regmap, 0x18, (MIPI_Timing[vfp] % 256)); //vfp
|
|
regmap_write(lt8911exb->regmap, 0x19, (MIPI_Timing[hfp] / 256));
|
|
regmap_write(lt8911exb->regmap, 0x1a, (MIPI_Timing[hfp] % 256)); //hfp
|
|
|
|
-
|
|
+#ifdef _uart_debug_
|
|
DRM_INFO("------\n");
|
|
DRM_INFO("MIPI_Timing[vtotal] / 256 = %d\n", MIPI_Timing[vtotal] / 256);
|
|
DRM_INFO("MIPI_Timing[vtotal] 256 = %d\n", MIPI_Timing[vtotal] % 256);
|
|
@@ -257,7 +246,6 @@ void lt8911exb_mipi_video_timing(struct lt8911exb *lt8911exb)
|
|
DRM_INFO("MIPI_Timing[hfp] 256 = %d\n", MIPI_Timing[hfp] % 256);
|
|
DRM_INFO("------\n");
|
|
|
|
-
|
|
regmap_read(lt8911exb->regmap, 0x0d, &tmp);
|
|
DRM_DEBUG_ATOMIC("0x0d = %d\n",tmp);
|
|
regmap_read(lt8911exb->regmap, 0x0e, &tmp);
|
|
@@ -290,11 +278,12 @@ void lt8911exb_mipi_video_timing(struct lt8911exb *lt8911exb)
|
|
DRM_DEBUG_ATOMIC("0x19 = %d\n",tmp);
|
|
regmap_read(lt8911exb->regmap, 0x1a, &tmp);
|
|
DRM_DEBUG_ATOMIC("0x1a = %d\n",tmp);
|
|
+#endif
|
|
}
|
|
|
|
void lt8911exb_edp_video_cfg(struct lt8911exb *lt8911exb)
|
|
{
|
|
- unsigned int tmp;
|
|
+ __maybe_unused unsigned int tmp;
|
|
|
|
regmap_write(lt8911exb->regmap, 0xff, 0xa8);
|
|
regmap_write(lt8911exb->regmap, 0x2d, 0x88); // MSA from register
|
|
@@ -314,6 +303,7 @@ void lt8911exb_edp_video_cfg(struct lt8911exb *lt8911exb)
|
|
regmap_write(lt8911exb->regmap, 0x15, (MIPI_Timing[vact] / 256));
|
|
regmap_write(lt8911exb->regmap, 0x16, (MIPI_Timing[vact] % 256));
|
|
|
|
+#ifdef _uart_debug_
|
|
DRM_INFO("------\n");
|
|
DRM_INFO("(u8)( MIPI_Timing[htotal] / 256 ) = %d\n", (MIPI_Timing[htotal] / 256));
|
|
DRM_INFO("(u8)( MIPI_Timing[htotal] 256 ) = %d\n", (MIPI_Timing[htotal] % 256));
|
|
@@ -366,14 +356,16 @@ void lt8911exb_edp_video_cfg(struct lt8911exb *lt8911exb)
|
|
DRM_DEBUG_ATOMIC("0x15 = %d\n",tmp);
|
|
regmap_read(lt8911exb->regmap, 0x16, &tmp);
|
|
DRM_DEBUG_ATOMIC("0x16 = %d\n",tmp);
|
|
+#endif
|
|
}
|
|
|
|
void lt8911exb_read_edid(struct lt8911exb *lt8911exb)
|
|
{
|
|
+#ifdef _read_edid_
|
|
u8 i, j;
|
|
unsigned int reg;
|
|
|
|
- DRM_INFO("lt8911exb_read_edid\n");
|
|
+ DRM_INFO("%s()\n", __func__);
|
|
|
|
regmap_write(lt8911exb->regmap, 0xff, 0xac );
|
|
regmap_write(lt8911exb->regmap, 0x00, 0x20 ); //Soft Link train
|
|
@@ -408,7 +400,7 @@ void lt8911exb_read_edid(struct lt8911exb *lt8911exb)
|
|
regmap_write(lt8911exb->regmap, 0x2b, 0x50 );
|
|
regmap_write(lt8911exb->regmap, 0x2b, 0x0f );
|
|
regmap_write(lt8911exb->regmap, 0x2c, 0x00 ); //start Aux read edid
|
|
- mdelay(50); //more than 50ms
|
|
+ mdelay(50); //more than 50ms
|
|
|
|
regmap_read(lt8911exb->regmap, 0x39, ®);
|
|
DRM_INFO("lt8911exb_read_edid 0x39 0x%x\n", reg);
|
|
@@ -429,16 +421,16 @@ void lt8911exb_read_edid(struct lt8911exb *lt8911exb)
|
|
return;
|
|
}
|
|
}
|
|
-#if 0
|
|
+
|
|
for( i = 0; i < 128; i++ ) //print edid data
|
|
{
|
|
if( ( i % 16 ) == 0 )
|
|
{
|
|
- printk( "\n" );
|
|
+ DRM_INFO( "\n" );
|
|
}
|
|
- printk( "%x", EDID_DATA[i] );
|
|
+ DRM_INFO( "%x", EDID_DATA[i] );
|
|
}
|
|
-#endif
|
|
+
|
|
|
|
EDID_Timing[hfp] = (EDID_DATA[0x41] & 0xC0) * 4 + EDID_DATA[0x3e];
|
|
EDID_Timing[hs] = (EDID_DATA[0x41] & 0x30) * 16 + EDID_DATA[0x3f];
|
|
@@ -451,14 +443,15 @@ void lt8911exb_read_edid(struct lt8911exb *lt8911exb)
|
|
EDID_Timing[vact] = (EDID_DATA[0x3d] & 0xf0) * 16 + EDID_DATA[0x3b];
|
|
EDID_Timing[vtotal] = (EDID_DATA[0x3d] & 0xf0 ) * 16 + EDID_DATA[0x3b] + ((EDID_DATA[0x3d] & 0x03) * 0x100 + EDID_DATA[0x3c]);
|
|
EDID_Timing[pclk_10khz] = EDID_DATA[0x37] * 0x100 + EDID_DATA[0x36];
|
|
- printk( "eDP Timing = { H_FP / H_pluse / H_BP / H_act / H_tol / V_FP / V_pluse / V_BP / V_act / V_tol / D_CLK };" );
|
|
- printk( "eDP Timing = { %d %d %d %d %d %d %d %d %d %d %d };\n",
|
|
+ DRM_INFO( "eDP Timing = { H_FP / H_pluse / H_BP / H_act / H_tol / V_FP / V_pluse / V_BP / V_act / V_tol / D_CLK };" );
|
|
+ DRM_INFO( "eDP Timing = { %d %d %d %d %d %d %d %d %d %d %d };\n",
|
|
(u32)EDID_Timing[hfp],(u32)EDID_Timing[hs],(u32)EDID_Timing[hbp],(u32)EDID_Timing[hact],(u32)EDID_Timing[htotal],
|
|
(u32)EDID_Timing[vfp],(u32)EDID_Timing[vs],(u32)EDID_Timing[vbp],(u32)EDID_Timing[vact],(u32)EDID_Timing[vtotal],(u32)EDID_Timing[pclk_10khz]);
|
|
}
|
|
|
|
return;
|
|
|
|
+#endif
|
|
}
|
|
|
|
void lt8911exb_setup(struct lt8911exb *lt8911exb)
|
|
@@ -469,7 +462,7 @@ void lt8911exb_setup(struct lt8911exb *lt8911exb)
|
|
u16 Temp16;
|
|
u32 chip_read = 0x00;
|
|
|
|
- DRM_INFO("\r\n lt8911exb_setup");
|
|
+ DRM_DEBUG("\r\n lt8911exb_setup");
|
|
|
|
/* init */
|
|
regmap_write(lt8911exb->regmap, 0xff, 0x81); // Change Reg bank
|
|
@@ -584,13 +577,13 @@ void lt8911exb_setup(struct lt8911exb *lt8911exb)
|
|
|
|
/*stage2 hs mode*/
|
|
// regmap_write(lt8911exb->regmap, 0x1e, 0x0A); //regmap_write(lt8911exb->regmap, 0x1e, 0x01 ); // 0x11
|
|
- DRM_INFO("\r\n lt8911exb_setup 0X1e 0x0a");
|
|
+ DRM_DEBUG("\r\n lt8911exb_setup 0X1e 0x0a");
|
|
regmap_write(lt8911exb->regmap, 0x1e, 0x0a);
|
|
regmap_write(lt8911exb->regmap, 0x23, 0xf0); // 0x80
|
|
|
|
regmap_write(lt8911exb->regmap, 0x2b, 0x80); // 0xa0
|
|
|
|
-#ifdef _Test_Pattern_
|
|
+#ifdef _test_pattern_
|
|
regmap_write(lt8911exb->regmap, 0x26, (pcr_m | 0x80));
|
|
#else
|
|
|
|
@@ -683,10 +676,10 @@ void lt8911exb_setup(struct lt8911exb *lt8911exb)
|
|
mdelay(5);
|
|
regmap_read(lt8911exb->regmap, 0x37, &chip_read);
|
|
if (chip_read & 0x02) {
|
|
- DRM_INFO("\r\n LT8911 tx pll locked");
|
|
+ DRM_DEBUG("\r\n LT8911 tx pll locked");
|
|
break;
|
|
} else {
|
|
- DRM_INFO("\r\n LT8911 tx pll unlocked");
|
|
+ DRM_DEBUG("\r\n LT8911 tx pll unlocked");
|
|
regmap_write(lt8911exb->regmap, 0xff, 0x81);
|
|
regmap_write(lt8911exb->regmap, 0x09, 0xfc);
|
|
regmap_write(lt8911exb->regmap, 0x09, 0xfd);
|
|
@@ -721,7 +714,7 @@ void lt8911exb_setup(struct lt8911exb *lt8911exb)
|
|
/*eDP Tx Digital */
|
|
regmap_write(lt8911exb->regmap, 0xff, 0xa8); // Change Reg bank
|
|
|
|
-#ifdef _Test_Pattern_
|
|
+#ifdef _test_pattern_
|
|
|
|
regmap_write(lt8911exb->regmap, 0x24, 0x50); // bit2 ~ bit 0 : test panttern image mode
|
|
regmap_write(lt8911exb->regmap, 0x25, 0x70); // bit6 ~ bit 4 : test Pattern color
|
|
@@ -767,7 +760,7 @@ void lt8911exb_video_check(struct lt8911exb *lt8911exb)
|
|
regmap_write(lt8911exb->regmap, 0xa1, 0x02 ); // DP scramble mode;
|
|
}
|
|
|
|
-// regmap_write(lt8911exb->regmap, 0x17, 0xf0 ); // 0xf0:Close scramble; 0xD0 : Open scramble
|
|
+ //regmap_write(lt8911exb->regmap, 0x17, 0xf0 ); // 0xf0:Close scramble; 0xD0 : Open scramble
|
|
|
|
regmap_write(lt8911exb->regmap, 0xff, 0x81);
|
|
regmap_write(lt8911exb->regmap, 0x09, 0x7d);
|
|
@@ -793,11 +786,11 @@ void lt8911exb_video_check(struct lt8911exb *lt8911exb)
|
|
DRM_DEBUG_ATOMIC("1-2 reg = %d\n",reg);
|
|
|
|
|
|
- DRM_INFO( "\r\nvideo check: mipi byteclk = %d ", reg ); // mipi byteclk = reg * 1000
|
|
- DRM_INFO( "\r\nvideo check: mipi bitrate = %d ", reg * 8); // mipi byteclk = reg * 1000
|
|
- DRM_INFO( "\r\nvideo check: mipi pclk = %d ", reg /3 * 4 * 1000); // mipi byteclk = reg * 1000
|
|
+ DRM_DEBUG( "\r\nvideo check: mipi byteclk = %d ", reg ); // mipi byteclk = reg * 1000
|
|
+ DRM_DEBUG( "\r\nvideo check: mipi bitrate = %d ", reg * 8); // mipi byteclk = reg * 1000
|
|
+ DRM_DEBUG( "\r\nvideo check: mipi pclk = %d ", reg /3 * 4 * 1000); // mipi byteclk = reg * 1000
|
|
} else {
|
|
- DRM_INFO( "\r\nvideo check: mipi clk unstable" );
|
|
+ DRM_DEBUG( "\r\nvideo check: mipi clk unstable" );
|
|
}
|
|
|
|
/* mipi vtotal check*/
|
|
@@ -810,7 +803,7 @@ void lt8911exb_video_check(struct lt8911exb *lt8911exb)
|
|
reg = reg * 256 + temp2;
|
|
DRM_DEBUG_ATOMIC("2-1 reg = %d\n",reg);
|
|
|
|
- DRM_INFO( "\r\nvideo check: Vtotal = %d", reg);
|
|
+ DRM_DEBUG( "\r\nvideo check: Vtotal = %d", reg);
|
|
|
|
/* mipi word count check*/
|
|
regmap_write(lt8911exb->regmap, 0xff, 0xd0);
|
|
@@ -826,7 +819,7 @@ void lt8911exb_video_check(struct lt8911exb *lt8911exb)
|
|
DRM_DEBUG_ATOMIC( "\r\n3-1 reg = %d ", reg );
|
|
|
|
|
|
- DRM_INFO( "\r\nvideo check: Hact(word counter) = %d", reg);
|
|
+ DRM_DEBUG( "\r\nvideo check: Hact(word counter) = %d", reg);
|
|
|
|
/* mipi Vact check*/
|
|
//reg = LT8911EXB_IIC_Read_byte( 0x85 );
|
|
@@ -838,7 +831,7 @@ void lt8911exb_video_check(struct lt8911exb *lt8911exb)
|
|
reg = reg * 256 + temp2;
|
|
DRM_DEBUG_ATOMIC( "\r\n4-1 reg = %d ", reg );
|
|
|
|
- DRM_INFO( "\r\nvideo check: Vact = %d", reg);
|
|
+ DRM_DEBUG( "\r\nvideo check: Vact = %d", reg);
|
|
|
|
}
|
|
|
|
@@ -904,7 +897,6 @@ unsigned int DpcdRead( struct lt8911exb *lt8911exb, u32 Address )
|
|
regmap_write(lt8911exb->regmap, 0x2c, 0x00); //start Aux read edid
|
|
|
|
mdelay(50); //more than 10ms
|
|
- //reg = LT8911EXB_IIC_Read_byte( 0x25 );
|
|
regmap_read(lt8911exb->regmap, 0x25, ®);
|
|
if ((reg & 0x0f) == 0x0c) {
|
|
regmap_read(lt8911exb->regmap, 0x39, &temp);
|
|
@@ -935,7 +927,7 @@ void lt8911exb_link_train(struct lt8911exb *lt8911exb)
|
|
|
|
regmap_write(lt8911exb->regmap, 0xff, 0x85);
|
|
|
|
-// regmap_write(lt8911exb->regmap, 0x17, 0xf0 ); // turn off scramble
|
|
+ //regmap_write(lt8911exb->regmap, 0x17, 0xf0 ); // turn off scramble
|
|
|
|
if (ScrambleMode) {
|
|
regmap_write(lt8911exb->regmap, 0xa1, 0x82); // eDP scramble mode;
|
|
@@ -999,16 +991,11 @@ void lt8911exb_reset(struct lt8911exb *lt8911exb)
|
|
}
|
|
|
|
gpiod_direction_output(lt8911exb->reset_gpio, 1);
|
|
-
|
|
usleep_range(100*1000, 150*1000); //150ms
|
|
gpiod_direction_output(lt8911exb->reset_gpio, 0);
|
|
-
|
|
usleep_range(100*1000, 150*1000); //150ms
|
|
gpiod_direction_output(lt8911exb->reset_gpio, 1);
|
|
-
|
|
usleep_range(100*1000, 150*1000); //150ms
|
|
- // gpiod_direction_input(lt8911exb->reset_gpio);
|
|
- // usleep_range(100*1000, 150*1000); //150ms
|
|
}
|
|
|
|
void LT8911EX_TxSwingPreSet(struct lt8911exb *lt8911exb)
|
|
@@ -1031,25 +1018,20 @@ void LT8911EXB_LinkTrainResultCheck( struct lt8911exb *lt8911exb)
|
|
{
|
|
#ifdef _link_train_enable_
|
|
u8 i;
|
|
- //u8 val;
|
|
unsigned int val;
|
|
- //int ret;
|
|
|
|
regmap_write(lt8911exb->regmap, 0xff, 0xac);
|
|
for (i = 0; i < 10; i++) {
|
|
- //val = LT8911EXB_IIC_Read_byte( 0x82 );
|
|
regmap_read(lt8911exb->regmap, 0x82, &val);
|
|
- DRM_INFO("\r\n0x82: 0x%x", val);
|
|
+ DRM_DEBUG("\r\n0x82: 0x%x", val);
|
|
if (val & 0x20) {
|
|
if ((val & 0x1f) == 0x1e) {
|
|
#ifdef _uart_debug_
|
|
- // DRM_DEBUG_ATOMIC("\r\nLT8911_LinkTrainResultCheck: edp link train successed: 0x%bx", val);
|
|
DRM_INFO("\r\nedp link train successed: 0x%x", val);
|
|
#endif
|
|
return;
|
|
} else {
|
|
#ifdef _uart_debug_
|
|
- //DRM_DEBUG_ATOMIC("\r\nLT8911_LinkTrainResultCheck: edp link train failed: 0x%bx", val);
|
|
DRM_INFO("\r\nedp link train failed: 0x%x", val);
|
|
#endif
|
|
regmap_write(lt8911exb->regmap, 0xff, 0xac);
|
|
@@ -1061,16 +1043,13 @@ void LT8911EXB_LinkTrainResultCheck( struct lt8911exb *lt8911exb)
|
|
regmap_write(lt8911exb->regmap, 0x14, 0x84);
|
|
mdelay(50);
|
|
regmap_write(lt8911exb->regmap, 0x14, 0xc0);
|
|
- //DRM_DEBUG_ATOMIC("\r\nLT8911_LinkTrainResultCheck: Enable eDP video output while linktrian fail");
|
|
}
|
|
|
|
#ifdef _uart_debug_
|
|
|
|
- //val = LT8911EXB_IIC_Read_byte( 0x83 );
|
|
regmap_read(lt8911exb->regmap, 0x83, &val);
|
|
//DRM_DEBUG_ATOMIC("\r\nLT8911_LinkTrainResultCheck: panel link rate: 0x%bx",val);
|
|
DRM_INFO( "\r\npanel link rate: 0x%x", val );
|
|
- //val = LT8911EXB_IIC_Read_byte( 0x84 );
|
|
regmap_read(lt8911exb->regmap, 0x84, &val);
|
|
//DRM_DEBUG_ATOMIC("\r\nLT8911_LinkTrainResultCheck: panel link count: 0x%bx",val);
|
|
DRM_INFO( "\r\npanel link count:0x%x ", val);
|
|
@@ -1092,24 +1071,22 @@ void LT8911EX_link_train_result(struct lt8911exb *lt8911exb)
|
|
unsigned int temp;
|
|
regmap_write(lt8911exb->regmap, 0xff, 0xac);
|
|
for (i = 0; i < 10; i++) {
|
|
- //reg = LT8911EXB_IIC_Read_byte( 0x82 );
|
|
regmap_read(lt8911exb->regmap, 0x82, ®);
|
|
- // Debug_DispStrNum( "\r\n0x82 = ", reg );
|
|
- DRM_INFO( "\r\n0x82 = 0x%x", reg );
|
|
+ DRM_DEBUG( "\r\n0x82 = 0x%x", reg );
|
|
if (reg & 0x20) {
|
|
if((reg & 0x1f) == 0x1e) {
|
|
- DRM_INFO("\r\nLink train success, 0x82 = 0x%x", reg);
|
|
+ DRM_DEBUG("\r\nLink train success, 0x82 = 0x%x", reg);
|
|
} else {
|
|
- DRM_INFO("\r\nLink train fail, 0x82 = 0x%x", reg);
|
|
+ DRM_DEBUG("\r\nLink train fail, 0x82 = 0x%x", reg);
|
|
}
|
|
|
|
regmap_read(lt8911exb->regmap, 0x83, &temp);
|
|
- DRM_INFO("\r\npanel link rate: 0x%x", temp);
|
|
+ DRM_DEBUG("\r\npanel link rate: 0x%x", temp);
|
|
regmap_read(lt8911exb->regmap, 0x84, &temp);
|
|
- DRM_INFO("\r\npanel link count: 0x%x", temp);
|
|
+ DRM_DEBUG("\r\npanel link count: 0x%x", temp);
|
|
return;
|
|
} else {
|
|
- DRM_INFO("\r\nlink trian on going...");
|
|
+ DRM_DEBUG("\r\nlink trian on going...");
|
|
}
|
|
mdelay(100);
|
|
}
|
|
@@ -1136,11 +1113,7 @@ void PCR_Status(struct lt8911exb *lt8911exb) // for debug
|
|
#endif
|
|
}
|
|
|
|
-
|
|
-//--------------------------------------enable function-------------------------------//
|
|
-
|
|
-
|
|
-static int lt8911exb_i2c_test(struct lt8911exb *lt8911exb)
|
|
+static int lt8911exb_chip_id(struct lt8911exb *lt8911exb)
|
|
{
|
|
u8 retry = 0;
|
|
unsigned int chip_id_h = 0, chip_id_m = 0, chip_id_l = 0;
|
|
@@ -1165,12 +1138,7 @@ static int lt8911exb_i2c_test(struct lt8911exb *lt8911exb)
|
|
regmap_read(lt8911exb->regmap, 0x01, &chip_id_m);
|
|
regmap_read(lt8911exb->regmap, 0x02, &chip_id_h);
|
|
// LT8911EXB i2c test success chipid: 0xe0517
|
|
- dev_info(lt8911exb->dev, "LT8911EXB i2c test success chipid: 0x%x%x%x\n", chip_id_h, chip_id_m, chip_id_l);
|
|
-
|
|
-// if (chip_id_h == 0 && chip_id_l == 0) {
|
|
-// dev_err(&client->dev, "LT8911EXB i2c test failed time %d\n", retry);
|
|
-// continue;
|
|
-// }
|
|
+ DRM_DEBUG("LT8911EXB i2c test success chipid: 0x%x%x%x\n", chip_id_h, chip_id_m, chip_id_l);
|
|
|
|
ret = 0;
|
|
break;
|
|
@@ -1183,47 +1151,19 @@ static int lt8911exb_panel_enable(struct drm_panel *panel)
|
|
{
|
|
struct lt8911exb *lt8911exb = panel_to_lt8911exb(panel);
|
|
|
|
- DRM_INFO(" %s() \n", __func__);
|
|
+ DRM_INFO("%s()\n", __func__);
|
|
|
|
- #if 0
|
|
gpiod_direction_output(lt8911exb->enable_gpio, 1);
|
|
usleep_range(100*1000, 150*1000); //150ms
|
|
+ gpiod_direction_output(lt8911exb->standby_gpio, 1);
|
|
+ usleep_range(100*1000, 150*1000); //150ms
|
|
|
|
- lt8911exb_reset(lt8911exb);
|
|
- lt8911exb_i2c_test(lt8911exb);
|
|
- lt8911exb_edp_video_cfg(lt8911exb); //void lt8911exb_edp_video_cfg( void )
|
|
- lt8911exb_setup(lt8911exb); //void LT8911EXB_init( void )
|
|
-
|
|
- ScrambleMode = 0;
|
|
-
|
|
- LT8911EX_TxSwingPreSet(lt8911exb);
|
|
- lt8911exb_link_train(lt8911exb); //void LT8911EX_link_train( void )
|
|
- LT8911EXB_LinkTrainResultCheck(lt8911exb);
|
|
- LT8911EX_link_train_result(lt8911exb);
|
|
- lt8911exb_video_check(lt8911exb); //just for Check MIPI Input //void LT8911EXB_video_check( void )
|
|
-
|
|
- // DRM_DEBUG_ATOMIC("\r\nDpcdRead(0x0202) = 0x%x\r\n",DpcdRead(lt8911exb, 0x0202));
|
|
- DRM_INFO("\r\nDpcdRead(0x0202) = 0x%x\r\n",DpcdRead(lt8911exb, 0x0202));
|
|
-
|
|
- PCR_Status(lt8911exb);
|
|
- #endif
|
|
+ gpiod_direction_output(lt8911exb->bl_gpio, 1);
|
|
|
|
schedule_delayed_work(<8911exb->init_work,
|
|
- msecs_to_jiffies(5000));
|
|
+ msecs_to_jiffies(2000));
|
|
lt8911exb->init_work_pending = true;
|
|
|
|
-
|
|
- #if 0
|
|
- // gpiod_direction_output(lt8911exb->enable_gpio, LT8911_LOW);
|
|
- gpiod_direction_output(lt8911exb->enable_gpio, 0);
|
|
-
|
|
- usleep_range(100*1000, 150*1000); //150ms
|
|
- // gpiod_direction_output(lt8911exb->enable_gpio, LT8911_HIGH);
|
|
- gpiod_direction_output(lt8911exb->enable_gpio, 1);
|
|
-
|
|
- usleep_range(100*1000, 150*1000); //150ms
|
|
- #endif
|
|
-
|
|
return 0;
|
|
}
|
|
|
|
@@ -1231,8 +1171,12 @@ static int lt8911exb_panel_disable(struct drm_panel *panel)
|
|
{
|
|
struct lt8911exb *lt8911exb = panel_to_lt8911exb(panel);
|
|
|
|
- DRM_INFO(" %s() \n", __func__);
|
|
+ DRM_INFO("%s()\n", __func__);
|
|
+
|
|
+ gpiod_direction_output(lt8911exb->bl_gpio, 0);
|
|
|
|
+ gpiod_direction_output(lt8911exb->standby_gpio, 0);
|
|
+ usleep_range(100*1000, 150*1000); //150ms
|
|
gpiod_direction_output(lt8911exb->enable_gpio, 0);
|
|
usleep_range(100*1000, 150*1000); //150ms
|
|
|
|
@@ -1250,7 +1194,7 @@ static int lt8911exb_panel_get_modes(struct drm_panel *panel,
|
|
unsigned int i, num = 0;
|
|
static const u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
|
|
|
|
- DRM_INFO(" %s() \n", __func__);
|
|
+ DRM_DEBUG("%s()\n", __func__);
|
|
|
|
for (i = 0; i < ARRAY_SIZE(lt8911exb_panel_modes); i++) {
|
|
const struct drm_display_mode *m = <8911exb_panel_modes[i];
|
|
@@ -1303,14 +1247,14 @@ static void init_work_func(struct work_struct *work)
|
|
struct lt8911exb *lt8911exb = container_of(work, struct lt8911exb,
|
|
init_work.work);
|
|
|
|
- DRM_INFO(" %s() \n", __func__);
|
|
+ DRM_DEBUG(" %s() \n", __func__);
|
|
|
|
gpiod_direction_output(lt8911exb->enable_gpio, 1);
|
|
usleep_range(100*1000, 150*1000); //150ms
|
|
|
|
lt8911exb_reset(lt8911exb);
|
|
|
|
- lt8911exb_i2c_test(lt8911exb);
|
|
+ lt8911exb_chip_id(lt8911exb);
|
|
|
|
lt8911exb_edp_video_cfg(lt8911exb);
|
|
lt8911exb_setup(lt8911exb);
|
|
@@ -1324,8 +1268,7 @@ static void init_work_func(struct work_struct *work)
|
|
LT8911EX_link_train_result(lt8911exb);
|
|
lt8911exb_video_check(lt8911exb); //just for Check MIPI Input
|
|
|
|
- // DRM_DEBUG_ATOMIC("\r\nDpcdRead(0x0202) = 0x%x\r\n",DpcdRead(lt8911exb, 0x0202));
|
|
- DRM_INFO("\r\nDpcdRead(0x0202) = 0x%x\r\n",DpcdRead(lt8911exb, 0x0202));
|
|
+ DRM_DEBUG("\r\nDpcdRead(0x0202) = 0x%x\r\n",DpcdRead(lt8911exb, 0x0202));
|
|
|
|
PCR_Status(lt8911exb);
|
|
|
|
@@ -1343,18 +1286,17 @@ static int lt8911exb_probe(struct i2c_client *client,
|
|
|
|
struct device_node *lcd_node;
|
|
int rc;
|
|
- // const void *p;
|
|
const char *str;
|
|
char lcd_path[60];
|
|
const char *lcd_name;
|
|
|
|
struct mipi_dsi_device_info info = {
|
|
.type = IT8911_DSI_DRIVER_NAME,
|
|
- .channel = 0, //0,
|
|
+ .channel = 0,
|
|
.node = NULL,
|
|
};
|
|
|
|
- DRM_INFO("%s()\n", __func__);
|
|
+ DRM_DEBUG("%s()\n", __func__);
|
|
|
|
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
|
|
dev_err(&client->dev, "Failed check I2C functionality");
|
|
@@ -1402,12 +1344,7 @@ static int lt8911exb_probe(struct i2c_client *client,
|
|
return PTR_ERR(lt8911exb->reset_gpio);
|
|
}
|
|
|
|
- gpiod_direction_output(lt8911exb->reset_gpio, 1);
|
|
- usleep_range(100*1000, 150*1000); //150ms
|
|
- gpiod_direction_output(lt8911exb->reset_gpio, 0);
|
|
- usleep_range(100*1000, 150*1000); //150ms
|
|
- gpiod_direction_output(lt8911exb->reset_gpio, 1);
|
|
- usleep_range(100*1000, 150*1000); //150ms
|
|
+ lt8911exb_reset(lt8911exb);
|
|
|
|
lt8911exb->bl_gpio = devm_gpiod_get_optional(dev, "bl",
|
|
GPIOD_IN);
|
|
@@ -1420,7 +1357,7 @@ static int lt8911exb_probe(struct i2c_client *client,
|
|
i2c_set_clientdata(client, lt8911exb);
|
|
|
|
//check i2c communicate
|
|
- ret = lt8911exb_i2c_test(lt8911exb); //void LT8911EX_ChipID( void )
|
|
+ ret = lt8911exb_chip_id(lt8911exb);
|
|
if (ret < 0) {
|
|
dev_err(&client->dev, "Failed communicate with IC use I2C\n");
|
|
return ret;
|
|
@@ -1430,14 +1367,10 @@ static int lt8911exb_probe(struct i2c_client *client,
|
|
if (!endpoint)
|
|
return -ENODEV;
|
|
|
|
- DRM_INFO(" %s() endpoint %s\n", __func__, endpoint->full_name);
|
|
-
|
|
dsi_host_node = of_graph_get_remote_port_parent(endpoint);
|
|
if (!dsi_host_node)
|
|
goto error;
|
|
|
|
- DRM_INFO(" %s() dsi_host_node %s\n", __func__, dsi_host_node->full_name);
|
|
-
|
|
rc = of_property_read_string(dsi_host_node, "force-attached", &str);
|
|
if (!rc)
|
|
lcd_name = str;
|
|
@@ -1452,7 +1385,6 @@ static int lt8911exb_probe(struct i2c_client *client,
|
|
|
|
DRM_INFO("%pOF: find %s node\n", dsi_host_node, lcd_name);
|
|
|
|
-
|
|
host = of_find_mipi_dsi_host_by_node(dsi_host_node);
|
|
of_node_put(dsi_host_node);
|
|
if (!host) {
|
|
@@ -1461,7 +1393,7 @@ static int lt8911exb_probe(struct i2c_client *client,
|
|
}
|
|
|
|
drm_panel_init(<8911exb->base, dev, <8911exb_panel_funcs,
|
|
- DRM_MODE_CONNECTOR_eDP);//DRM_MODE_CONNECTOR_eDP DRM_MODE_CONNECTOR_DSI
|
|
+ DRM_MODE_CONNECTOR_DSI);
|
|
|
|
/* This appears last, as it's what will unblock the DSI host
|
|
* driver's component bind function.
|
|
@@ -1474,7 +1406,6 @@ static int lt8911exb_probe(struct i2c_client *client,
|
|
goto error;
|
|
of_node_put(endpoint);
|
|
|
|
-
|
|
lt8911exb->dsi = mipi_dsi_device_register_full(host, &info);
|
|
if (IS_ERR(lt8911exb->dsi)) {
|
|
dev_err(dev, "DSI device registration failed: %ld\n",
|
|
@@ -1494,7 +1425,7 @@ static void lt8911exb_remove(struct i2c_client *client)
|
|
{
|
|
struct lt8911exb *lt8911exb = i2c_get_clientdata(client);
|
|
|
|
- DRM_INFO("%s()\n", __func__);
|
|
+ DRM_DEBUG("%s()\n", __func__);
|
|
|
|
mipi_dsi_detach(lt8911exb->dsi);
|
|
|
|
@@ -1529,11 +1460,9 @@ static int lt8911exb_dsi_probe(struct mipi_dsi_device *dsi)
|
|
{
|
|
int ret;
|
|
|
|
-
|
|
- DRM_INFO("%s()\n", __func__);
|
|
+ DRM_DEBUG("%s()\n", __func__);
|
|
|
|
dsi->lanes = 4;
|
|
-
|
|
dsi->mode_flags = (MIPI_DSI_MODE_VIDEO |
|
|
MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
|
|
MIPI_DSI_MODE_LPM);
|
|
@@ -1548,9 +1477,18 @@ static int lt8911exb_dsi_probe(struct mipi_dsi_device *dsi)
|
|
return ret;
|
|
}
|
|
|
|
+static const struct of_device_id spacemit_edp_of_match[] = {
|
|
+ { .compatible = "spacemit,edp-panel" },
|
|
+ { /* sentinel */ }
|
|
+};
|
|
+MODULE_DEVICE_TABLE(of, spacemit_edp_of_match);
|
|
+
|
|
static struct mipi_dsi_driver lt8911exb_dsi_driver = {
|
|
- .driver.name = IT8911_DSI_DRIVER_NAME,
|
|
.probe = lt8911exb_dsi_probe,
|
|
+ .driver = {
|
|
+ .name = IT8911_DSI_DRIVER_NAME,
|
|
+ .of_match_table = spacemit_edp_of_match,
|
|
+ },
|
|
};
|
|
|
|
|
|
@@ -1559,7 +1497,6 @@ static int __init init_lt8911exb(void)
|
|
int err;
|
|
|
|
DRM_INFO("%s()\n", __func__);
|
|
-
|
|
mipi_dsi_driver_register(<8911exb_dsi_driver);
|
|
err = i2c_add_driver(<8911exb_driver);
|
|
|
|
@@ -1571,7 +1508,6 @@ module_init(init_lt8911exb);
|
|
static void __exit exit_lt8911exb(void)
|
|
{
|
|
DRM_INFO("%s()\n", __func__);
|
|
-
|
|
i2c_del_driver(<8911exb_driver);
|
|
mipi_dsi_driver_unregister(<8911exb_dsi_driver);
|
|
}
|
|
diff --git a/drivers/gpu/drm/spacemit/lt9711.c b/drivers/gpu/drm/spacemit/lt9711.c
|
|
new file mode 100644
|
|
index 000000000000..111111111111
|
|
--- /dev/null
|
|
+++ b/drivers/gpu/drm/spacemit/lt9711.c
|
|
@@ -0,0 +1,406 @@
|
|
+// SPDX-License-Identifier: GPL-2.0
|
|
+/*
|
|
+ * Copyright (C) 2023 Spacemit Co., Ltd.
|
|
+ *
|
|
+ */
|
|
+
|
|
+#include <linux/auxiliary_bus.h>
|
|
+#include <linux/bits.h>
|
|
+#include <linux/clk.h>
|
|
+#include <linux/debugfs.h>
|
|
+#include <linux/gpio/consumer.h>
|
|
+#include <linux/gpio/driver.h>
|
|
+#include <linux/i2c.h>
|
|
+#include <linux/iopoll.h>
|
|
+#include <linux/module.h>
|
|
+#include <linux/of_graph.h>
|
|
+#include <linux/pm_runtime.h>
|
|
+#include <linux/regmap.h>
|
|
+#include <linux/regulator/consumer.h>
|
|
+#include <linux/media-bus-format.h>
|
|
+#include <linux/atomic.h>
|
|
+#include <linux/workqueue.h>
|
|
+#include <asm/unaligned.h>
|
|
+#include <drm/drm_atomic.h>
|
|
+#include <drm/drm_atomic_helper.h>
|
|
+#include <drm/drm_bridge.h>
|
|
+#include <drm/drm_mipi_dsi.h>
|
|
+#include <drm/drm_of.h>
|
|
+#include <drm/drm_panel.h>
|
|
+#include <drm/drm_print.h>
|
|
+#include <drm/drm_probe_helper.h>
|
|
+#include <drm/drm_bridge.h>
|
|
+#include <linux/delay.h>
|
|
+#include <drm/display/drm_dp_aux_bus.h>
|
|
+#include <drm/display/drm_dp_helper.h>
|
|
+
|
|
+#define IT9711_DSI_DRIVER_NAME "spacemit-dp-drv"
|
|
+#define MIPI_DSI_1920x1080 1
|
|
+
|
|
+static const struct drm_display_mode lt9711_panel_modes[] = {
|
|
+
|
|
+#if MIPI_DSI_1920x1080
|
|
+ {
|
|
+ .clock = 142857143 / 1000,
|
|
+ .hdisplay = 1920,
|
|
+ .hsync_start = 1920 + 88,
|
|
+ .hsync_end = 1920 + 88 + 148,
|
|
+ .htotal = 1920 + 88 + 148 + 44,
|
|
+ .vdisplay = 1080,
|
|
+ .vsync_start = 1080 + 4,
|
|
+ .vsync_end = 1080 + 4 + 36,
|
|
+ .vtotal = 1080 + 4 + 36 + 5,
|
|
+ },
|
|
+#endif
|
|
+
|
|
+};
|
|
+
|
|
+struct lt9711 {
|
|
+ struct device *dev;
|
|
+ struct drm_bridge bridge;
|
|
+ struct drm_connector connector;
|
|
+
|
|
+ struct regmap *regmap;
|
|
+
|
|
+ struct gpio_desc *reset_gpio;
|
|
+
|
|
+ struct i2c_client *client;
|
|
+ struct drm_panel base;
|
|
+ struct mipi_dsi_device *dsi;
|
|
+
|
|
+ enum drm_connector_status status;
|
|
+
|
|
+ struct delayed_work init_work;
|
|
+ bool init_work_pending;
|
|
+};
|
|
+
|
|
+static const struct regmap_config lt9711_regmap_config = {
|
|
+ .reg_bits = 8,
|
|
+ .val_bits = 8,
|
|
+ .max_register = 0xff,
|
|
+};
|
|
+
|
|
+static struct lt9711 *panel_to_lt9711(struct drm_panel *panel)
|
|
+{
|
|
+ return container_of(panel, struct lt9711, base);
|
|
+}
|
|
+
|
|
+static int lt9711_i2c_detect(struct lt9711 *lt9711)
|
|
+{
|
|
+ u8 retry = 0;
|
|
+ unsigned int status = 0;
|
|
+ int ret = -EAGAIN;
|
|
+
|
|
+ while(retry++ < 3) {
|
|
+
|
|
+ ret = regmap_write(lt9711->regmap, 0xff, 0x80);
|
|
+ if(ret < 0) {
|
|
+ dev_err(lt9711->dev, "LT9711 i2c detect write addr:0xff failed\n");
|
|
+ continue;
|
|
+ }
|
|
+ usleep_range(100*1000, 150*1000); //150ms
|
|
+
|
|
+ regmap_read(lt9711->regmap, 0xd6, &status);
|
|
+ // LT9711 i2c detect success status: 0xee
|
|
+ DRM_INFO("LT9711 i2c detect success status: 0x%x\n", status);
|
|
+
|
|
+ if (0xee == status)
|
|
+ ret = 0;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int lt9711_panel_enable(struct drm_panel *panel)
|
|
+{
|
|
+ struct lt9711 *lt9711 = panel_to_lt9711(panel);
|
|
+
|
|
+ DRM_INFO(" %s() \n", __func__);
|
|
+
|
|
+ schedule_delayed_work(<9711->init_work,
|
|
+ msecs_to_jiffies(1000));
|
|
+ lt9711->init_work_pending = true;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int lt9711_panel_disable(struct drm_panel *panel)
|
|
+{
|
|
+ struct lt9711 *lt9711 = panel_to_lt9711(panel);
|
|
+
|
|
+ DRM_INFO(" %s() \n", __func__);
|
|
+
|
|
+ if (lt9711->init_work_pending) {
|
|
+ cancel_delayed_work_sync(<9711->init_work);
|
|
+ lt9711->init_work_pending = false;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int lt9711_panel_get_modes(struct drm_panel *panel,
|
|
+ struct drm_connector *connector)
|
|
+{
|
|
+ unsigned int i, num = 0;
|
|
+ static const u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
|
|
+
|
|
+ DRM_DEBUG(" %s() \n", __func__);
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(lt9711_panel_modes); i++) {
|
|
+ const struct drm_display_mode *m = <9711_panel_modes[i];
|
|
+ struct drm_display_mode *mode;
|
|
+
|
|
+ mode = drm_mode_duplicate(connector->dev, m);
|
|
+ if (!mode) {
|
|
+ dev_err(panel->dev, "failed to add mode %ux%u@%u\n",
|
|
+ m->hdisplay, m->vdisplay,
|
|
+ drm_mode_vrefresh(m));
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ mode->type |= DRM_MODE_TYPE_DRIVER;
|
|
+
|
|
+ if (i == 0)
|
|
+ mode->type |= DRM_MODE_TYPE_PREFERRED;
|
|
+
|
|
+ drm_mode_set_name(mode);
|
|
+ drm_mode_probed_add(connector, mode);
|
|
+ num++;
|
|
+ }
|
|
+
|
|
+ connector->display_info.bpc = 8;
|
|
+ // 1920x1080
|
|
+ #if MIPI_DSI_1920x1080
|
|
+ connector->display_info.width_mm = 309;
|
|
+ connector->display_info.height_mm = 174;
|
|
+ #endif
|
|
+
|
|
+ drm_display_info_set_bus_formats(&connector->display_info,
|
|
+ &bus_format, 1);
|
|
+ return num;
|
|
+}
|
|
+
|
|
+
|
|
+static const struct drm_panel_funcs lt9711_panel_funcs = {
|
|
+ .disable = lt9711_panel_disable,
|
|
+ .enable = lt9711_panel_enable,
|
|
+ .get_modes = lt9711_panel_get_modes,
|
|
+};
|
|
+
|
|
+static void init_work_func(struct work_struct *work)
|
|
+{
|
|
+ struct lt9711 *lt9711 = container_of(work, struct lt9711,
|
|
+ init_work.work);
|
|
+ DRM_DEBUG(" %s() \n", __func__);
|
|
+
|
|
+ lt9711_i2c_detect(lt9711);
|
|
+
|
|
+}
|
|
+
|
|
+static int lt9711_probe(struct i2c_client *client,
|
|
+ const struct i2c_device_id *id)
|
|
+{
|
|
+ struct lt9711 *lt9711;
|
|
+ struct device *dev = &client->dev;
|
|
+ int ret;
|
|
+
|
|
+ struct device_node *endpoint, *dsi_host_node;
|
|
+ struct mipi_dsi_host *host;
|
|
+
|
|
+ struct device_node *lcd_node;
|
|
+ int rc;
|
|
+ const char *str;
|
|
+ char lcd_path[60];
|
|
+ const char *lcd_name;
|
|
+
|
|
+ struct mipi_dsi_device_info info = {
|
|
+ .type = IT9711_DSI_DRIVER_NAME,
|
|
+ .channel = 0,
|
|
+ .node = NULL,
|
|
+ };
|
|
+
|
|
+ DRM_DEBUG("%s()\n", __func__);
|
|
+
|
|
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
|
|
+ dev_err(&client->dev, "Failed check I2C functionality");
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ lt9711 = devm_kzalloc(&client->dev, sizeof(*lt9711), GFP_KERNEL);
|
|
+ if (!lt9711)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ lt9711->dev = &client->dev;
|
|
+ lt9711->client = client;
|
|
+
|
|
+ //regmap i2c , maybe useless
|
|
+ lt9711->regmap = devm_regmap_init_i2c(client, <9711_regmap_config);
|
|
+ if (IS_ERR(lt9711->regmap)) {
|
|
+ dev_err(lt9711->dev, "regmap i2c init failed\n");
|
|
+ return PTR_ERR(lt9711->regmap);
|
|
+ }
|
|
+
|
|
+ i2c_set_clientdata(client, lt9711);
|
|
+
|
|
+ //check i2c communicate
|
|
+ ret = lt9711_i2c_detect(lt9711);
|
|
+ if (ret < 0) {
|
|
+ DRM_INFO("detect DP failed communicate with IC use I2C\n");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
|
|
+ if (!endpoint)
|
|
+ return -ENODEV;
|
|
+
|
|
+ dsi_host_node = of_graph_get_remote_port_parent(endpoint);
|
|
+ if (!dsi_host_node)
|
|
+ goto error;
|
|
+
|
|
+ rc = of_property_read_string(dsi_host_node, "force-attached", &str);
|
|
+ if (!rc)
|
|
+ lcd_name = str;
|
|
+
|
|
+ sprintf(lcd_path, "/lcds/%s", lcd_name);
|
|
+ lcd_node = of_find_node_by_path(lcd_path);
|
|
+ if (!lcd_node) {
|
|
+ DRM_ERROR("%pOF: could not find %s node\n", dsi_host_node, lcd_name);
|
|
+ of_node_put(endpoint);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ DRM_INFO("%pOF: find %s node\n", dsi_host_node, lcd_name);
|
|
+
|
|
+ host = of_find_mipi_dsi_host_by_node(dsi_host_node);
|
|
+ of_node_put(dsi_host_node);
|
|
+ if (!host) {
|
|
+ of_node_put(endpoint);
|
|
+ return -EPROBE_DEFER;
|
|
+ }
|
|
+
|
|
+ drm_panel_init(<9711->base, dev, <9711_panel_funcs,
|
|
+ DRM_MODE_CONNECTOR_DSI);
|
|
+
|
|
+ /* This appears last, as it's what will unblock the DSI host
|
|
+ * driver's component bind function.
|
|
+ */
|
|
+ drm_panel_add(<9711->base);
|
|
+
|
|
+ lt9711->base.dev->of_node = lcd_node;
|
|
+ info.node = of_node_get(of_graph_get_remote_port(endpoint));
|
|
+ if (!info.node)
|
|
+ goto error;
|
|
+ of_node_put(endpoint);
|
|
+
|
|
+ lt9711->dsi = mipi_dsi_device_register_full(host, &info);
|
|
+ if (IS_ERR(lt9711->dsi)) {
|
|
+ dev_err(dev, "DSI device registration failed: %ld\n",
|
|
+ PTR_ERR(lt9711->dsi));
|
|
+ return PTR_ERR(lt9711->dsi);
|
|
+ }
|
|
+
|
|
+ INIT_DELAYED_WORK(<9711->init_work, init_work_func);
|
|
+
|
|
+ return 0;
|
|
+error:
|
|
+ of_node_put(endpoint);
|
|
+ return -ENODEV;
|
|
+}
|
|
+
|
|
+static void lt9711_remove(struct i2c_client *client)
|
|
+{
|
|
+ struct lt9711 *lt9711 = i2c_get_clientdata(client);
|
|
+
|
|
+ DRM_DEBUG("%s()\n", __func__);
|
|
+
|
|
+ mipi_dsi_detach(lt9711->dsi);
|
|
+
|
|
+ drm_panel_remove(<9711->base);
|
|
+
|
|
+ mipi_dsi_device_unregister(lt9711->dsi);
|
|
+}
|
|
+
|
|
+static struct i2c_device_id lt9711_id[] = {
|
|
+ { "lontium,lt9711", 0 },
|
|
+ {}
|
|
+};
|
|
+MODULE_DEVICE_TABLE(i2c, lt9711_id);
|
|
+
|
|
+static const struct of_device_id lt9711_match_table[] = {
|
|
+ { .compatible = "lontium,lt9711" },
|
|
+ { }
|
|
+};
|
|
+MODULE_DEVICE_TABLE(of, lt9711_match_table);
|
|
+
|
|
+static struct i2c_driver lt9711_driver = {
|
|
+ .driver = {
|
|
+ .name = "lt9711",
|
|
+ .of_match_table = lt9711_match_table,
|
|
+ },
|
|
+ .probe = lt9711_probe,
|
|
+ .remove = lt9711_remove,
|
|
+ .id_table = lt9711_id,
|
|
+};
|
|
+
|
|
+static int lt9711_dsi_probe(struct mipi_dsi_device *dsi)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ DRM_DEBUG("%s()\n", __func__);
|
|
+
|
|
+ dsi->lanes = 4;
|
|
+ dsi->mode_flags = (MIPI_DSI_MODE_VIDEO |
|
|
+ MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
|
|
+ MIPI_DSI_MODE_LPM);
|
|
+ dsi->format = MIPI_DSI_FMT_RGB888;
|
|
+
|
|
+ ret = mipi_dsi_attach(dsi);
|
|
+ if (ret < 0) {
|
|
+ dev_err(&dsi->dev, "failed to attach dsi to host\n");
|
|
+ mipi_dsi_device_unregister(dsi);
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static const struct of_device_id spacemit_dp_of_match[] = {
|
|
+ { .compatible = "spacemit,dp-panel" },
|
|
+ { /* sentinel */ }
|
|
+};
|
|
+MODULE_DEVICE_TABLE(of, spacemit_edp_of_match);
|
|
+
|
|
+static struct mipi_dsi_driver lt9711_dsi_driver = {
|
|
+ .probe = lt9711_dsi_probe,
|
|
+ .driver = {
|
|
+ .name = IT9711_DSI_DRIVER_NAME,
|
|
+ .of_match_table = spacemit_dp_of_match,
|
|
+ },
|
|
+};
|
|
+
|
|
+
|
|
+static int __init init_lt9711(void)
|
|
+{
|
|
+ int err;
|
|
+
|
|
+ DRM_INFO("%s()\n", __func__);
|
|
+
|
|
+ mipi_dsi_driver_register(<9711_dsi_driver);
|
|
+ err = i2c_add_driver(<9711_driver);
|
|
+
|
|
+ return err;
|
|
+}
|
|
+
|
|
+module_init(init_lt9711);
|
|
+
|
|
+static void __exit exit_lt9711(void)
|
|
+{
|
|
+ DRM_INFO("%s()\n", __func__);
|
|
+
|
|
+ i2c_del_driver(<9711_driver);
|
|
+ mipi_dsi_driver_unregister(<9711_dsi_driver);
|
|
+}
|
|
+module_exit(exit_lt9711);
|
|
+
|
|
+MODULE_DESCRIPTION("LT9711_MIPI to DP Reg Setting driver");
|
|
+MODULE_LICENSE("GPL v2");
|
|
diff --git a/drivers/gpu/drm/spacemit/spacemit_dsi.c b/drivers/gpu/drm/spacemit/spacemit_dsi.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/gpu/drm/spacemit/spacemit_dsi.c
|
|
+++ b/drivers/gpu/drm/spacemit/spacemit_dsi.c
|
|
@@ -462,7 +462,7 @@ static int spacemit_dsi_connector_get_modes(struct drm_connector *connector)
|
|
{
|
|
struct spacemit_dsi *dsi = connector_to_dsi(connector);
|
|
|
|
- DRM_INFO("%s()\n", __func__);
|
|
+ DRM_DEBUG("%s()\n", __func__);
|
|
|
|
return drm_panel_get_modes(dsi->panel, connector);
|
|
}
|
|
@@ -473,7 +473,7 @@ spacemit_dsi_connector_mode_valid(struct drm_connector *connector,
|
|
{
|
|
enum drm_mode_status mode_status = MODE_OK;
|
|
|
|
- DRM_INFO("%s()\n", __func__);
|
|
+ DRM_DEBUG("%s()\n", __func__);
|
|
|
|
return mode_status;
|
|
}
|
|
@@ -496,7 +496,7 @@ static struct drm_connector_helper_funcs spacemit_dsi_connector_helper_funcs = {
|
|
static enum drm_connector_status
|
|
spacemit_dsi_connector_detect(struct drm_connector *connector, bool force)
|
|
{
|
|
- DRM_INFO("%s()\n", __func__);
|
|
+ DRM_DEBUG("%s()\n", __func__);
|
|
|
|
return connector_status_connected;
|
|
}
|
|
@@ -633,7 +633,7 @@ static void spacemit_dsi_unbind(struct device *dev,
|
|
struct device *master, void *data)
|
|
{
|
|
/* do nothing */
|
|
- DRM_INFO("%s()\n", __func__);
|
|
+ DRM_DEBUG("%s()\n", __func__);
|
|
|
|
}
|
|
|
|
diff --git a/drivers/gpu/drm/spacemit/spacemit_hdmi.c b/drivers/gpu/drm/spacemit/spacemit_hdmi.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/gpu/drm/spacemit/spacemit_hdmi.c
|
|
+++ b/drivers/gpu/drm/spacemit/spacemit_hdmi.c
|
|
@@ -40,7 +40,7 @@
|
|
|
|
|
|
struct hdmi_data_info {
|
|
- uint8_t edid[128];
|
|
+ uint8_t edid[EDID_LENGTH];
|
|
int vic;
|
|
bool sink_has_audio;
|
|
unsigned int enc_in_format;
|
|
@@ -409,7 +409,7 @@ static void hdmi_i2c_read(struct spacemit_hdmi *hdmi, uint8_t addr, uint8_t* mes
|
|
value |= SPACEMIT_HDMI_DDC_DONE;
|
|
|
|
hdmi_writeb(hdmi, 0xc, value);
|
|
- udelay(5);
|
|
+ udelay(100);
|
|
|
|
DRM_DEBUG("hdmi_i2c_read --%u\r\n", length);
|
|
|
|
@@ -459,6 +459,7 @@ static int hdmi_i2c_write(struct spacemit_hdmi *hdmi, uint8_t addr, uint8_t* mes
|
|
DRM_INFO("%s wait hdmi ddc command done timeout\n", __func__);
|
|
return -1;
|
|
}
|
|
+ udelay(100);
|
|
|
|
DRM_DEBUG("hdmi_i2c_write --%u\r\n", length);
|
|
|
|
@@ -469,16 +470,26 @@ static int hdmi_i2c_write(struct spacemit_hdmi *hdmi, uint8_t addr, uint8_t* mes
|
|
int edid_read (struct spacemit_hdmi *hdmi){
|
|
int i;
|
|
struct hdmi_data_info *hdmi_data = hdmi->hdmi_data;
|
|
+ uint8_t offset;
|
|
+ int result;
|
|
|
|
DRM_DEBUG("%s()\n", __func__);
|
|
|
|
- if (0 == hdmi_i2c_write(hdmi, 0x50, hdmi_data->edid, 1))
|
|
- hdmi_i2c_read(hdmi, 0x50, hdmi_data->edid, EDID_LENGTH);
|
|
- else
|
|
- return -1;
|
|
+ for(i = 0; i < 8; i++) {
|
|
+ offset = i * 16;
|
|
+ result = hdmi_i2c_write(hdmi, 0x50, &offset, 1);
|
|
+ if (result < 0)
|
|
+ break;
|
|
+ hdmi_i2c_read(hdmi, 0x50, hdmi_data->edid + offset, 16);
|
|
+ }
|
|
+
|
|
+ if (result < 0) {
|
|
+ memset(hdmi_data->edid, 0x00, EDID_LENGTH);
|
|
+ return result;
|
|
+ }
|
|
|
|
for(i = 0; i < EDID_LENGTH; i += 4){
|
|
- DRM_INFO("EDID 0x%x: 0x%x, 0x%x, 0x%x, 0x%x\r\n", i,
|
|
+ DRM_DEBUG("EDID 0x%x: 0x%x, 0x%x, 0x%x, 0x%x\r\n", i,
|
|
hdmi_data->edid[i], hdmi_data->edid[i+1], hdmi_data->edid[i+2], hdmi_data->edid[i+3]);
|
|
}
|
|
|
|
@@ -565,7 +576,7 @@ void hdmi_init (struct spacemit_hdmi *hdmi, int pixel_clock, int bit_depth){
|
|
pll_reg(hdmi, pixel_clock, bit_depth);
|
|
writel(0x03, hdmi->regs + 0xe4);
|
|
value = readl_relaxed(hdmi->regs + 0xe4);
|
|
- DRM_INFO("%s() hdmi pll lock status 0x%x\n", __func__, value);
|
|
+ DRM_DEBUG("%s() hdmi pll lock status 0x%x\n", __func__, value);
|
|
// while ( (value & 0x10000) != 0) {
|
|
// value = readl_relaxed(hdmi->regs + 0xe4);
|
|
// }
|
|
@@ -691,7 +702,7 @@ spacemit_hdmi_connector_detect(struct drm_connector *connector, bool force)
|
|
int ret;
|
|
enum drm_connector_status status;
|
|
|
|
- DRM_INFO("%s() \n", __func__);
|
|
+ DRM_DEBUG("%s() \n", __func__);
|
|
|
|
ret = pm_runtime_get_sync(hdmi->dev);
|
|
if (ret < 0) {
|
|
@@ -720,13 +731,13 @@ static int spacemit_hdmi_connector_get_modes(struct drm_connector *connector)
|
|
struct edid *edid;
|
|
uint32_t value;
|
|
|
|
- DRM_INFO("%s() \n", __func__);
|
|
+ DRM_DEBUG("%s() \n", __func__);
|
|
|
|
if (hdmi->use_no_edid)
|
|
return drm_add_modes_noedid(connector, 1920, 1080);
|
|
|
|
value = hdmi_readb(hdmi, SPACEMIT_HDMI_PHY_STATUS);
|
|
- DRM_INFO("%s() hdmi status 0x%x\n", __func__, value);
|
|
+ DRM_DEBUG("%s() hdmi status 0x%x\n", __func__, value);
|
|
value &= ~(SPACEMIT_HDMI_DDC_OTHER_MASK | SPACEMIT_HDMI_DDC_DONE_MASK);
|
|
value |= (SPACEMIT_HDMI_HPD_IQR | SPACEMIT_HDMI_DDC_DONE | SPACEMIT_HDMI_DDC_NACK);
|
|
hdmi_writeb(hdmi, SPACEMIT_HDMI_PHY_STATUS, value);
|
|
@@ -853,7 +864,7 @@ static int spacemit_hdmi_bind(struct device *dev, struct device *master,
|
|
int irq;
|
|
int ret;
|
|
|
|
- DRM_INFO("%s() \n", __func__);
|
|
+ DRM_DEBUG("%s() \n", __func__);
|
|
|
|
hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
|
|
if (!hdmi)
|
|
@@ -932,7 +943,7 @@ static void spacemit_hdmi_unbind(struct device *dev, struct device *master,
|
|
struct spacemit_hdmi *hdmi = dev_get_drvdata(dev);
|
|
int ret;
|
|
|
|
- DRM_INFO("%s() \n", __func__);
|
|
+ DRM_DEBUG("%s() \n", __func__);
|
|
|
|
hdmi->connector.funcs->destroy(&hdmi->connector);
|
|
hdmi->encoder.funcs->destroy(&hdmi->encoder);
|
|
@@ -978,7 +989,7 @@ static int hdmi_rt_pm_resume(struct device *dev)
|
|
clk_prepare_enable(hdmi->hdmi_mclk);
|
|
|
|
clk_val = clk_get_rate(hdmi->hdmi_mclk);
|
|
- DRM_INFO("get hdmi mclk=%lld\n", clk_val);
|
|
+ DRM_DEBUG("get hdmi mclk=%lld\n", clk_val);
|
|
if(clk_val != DPU_MCLK_DEFAULT){
|
|
clk_val = clk_round_rate(hdmi->hdmi_mclk, DPU_MCLK_DEFAULT);
|
|
clk_set_rate(hdmi->hdmi_mclk, clk_val);
|
|
diff --git a/drivers/pci/controller/dwc/pcie-k1x.c b/drivers/pci/controller/dwc/pcie-k1x.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/pci/controller/dwc/pcie-k1x.c
|
|
+++ b/drivers/pci/controller/dwc/pcie-k1x.c
|
|
@@ -263,7 +263,6 @@ void porta_rterm(struct k1x_pcie *k1x)
|
|
u32 val;
|
|
|
|
//REG32(PMUA_REG_BASE + 0x3CC) = 0x4000003f;
|
|
- val = k1x_pcie_conf0_reg_readl(k1x, 0);
|
|
val = 0x4000003f;
|
|
k1x_pcie_conf0_reg_writel(k1x, 0 , val);
|
|
|
|
@@ -356,15 +355,13 @@ void porta_rterm(struct k1x_pcie *k1x)
|
|
k1x_pcie_phy0_reg_writel(k1x, (0x12 << 2), val);
|
|
|
|
//REG32(0xC0B10000 + (0x02 << 2)) = 0x00000B78; // PU_ADDR_CLK_CFG of lane0
|
|
- val = k1x_pcie_phy0_reg_readl(k1x, (0x02 << 2));
|
|
val = 0x00000B78;
|
|
k1x_pcie_phy0_reg_writel(k1x, (0x02 << 2), val);
|
|
|
|
//REG32(0xC0B10000 + (0x06 << 2)) = 0x00000400; // force rcv done
|
|
- val = k1x_pcie_phy0_reg_readl(k1x, (0x06 << 2));
|
|
val = 0x00000400;
|
|
k1x_pcie_phy0_reg_writel(k1x, (0x06 << 2), val);
|
|
- printk("Now waiting portA resister tuning done...\n");
|
|
+ pr_debug("Now waiting portA resister tuning done...\n");
|
|
|
|
// force PCIE mpu_u3/pu_rx_lfps
|
|
//REG32(PCIE_PUPHY_REG_BASE + 0x6 * 4) |= (0x1 << 17) | (0x1 << 15);
|
|
@@ -379,7 +376,7 @@ void porta_rterm(struct k1x_pcie *k1x)
|
|
//rd_data = REG32(0xC0B10000 + 0x21 * 4);
|
|
rd_data = k1x_pcie_phy0_reg_readl(k1x, (0x21 * 4));
|
|
if (count++ > 5000) {
|
|
- printk(KERN_WARNING "read pcie0 phy rd_data time out.\n");
|
|
+ pr_err("read pcie0 phy rd_data time out.\n");
|
|
break;
|
|
}
|
|
} while (((rd_data >> 10) & 0x1) == 0); // waiting PCIe portA readonly_reg2[2] r_tune_done==1
|
|
@@ -392,8 +389,8 @@ void rterm_force(struct k1x_pcie *k1x, u32 pcie_rcal)
|
|
u32 val = 0;
|
|
|
|
lane = k1x->num_lanes;
|
|
- printk("pcie_rcal = 0x%08x\n", pcie_rcal);
|
|
- printk("pcie port id = %d, lane num = %d\n", k1x->port_id, lane);
|
|
+ pr_debug("pcie_rcal = 0x%08x\n", pcie_rcal);
|
|
+ pr_debug("pcie port id = %d, lane num = %d\n", k1x->port_id, lane);
|
|
|
|
// 2.write pma0 rterm value LSB[3:0](read0nly1[3:0]) to lane0/1 rx_reg1
|
|
for (i = 0; i < lane; i++)
|
|
@@ -476,8 +473,8 @@ static int init_phy(struct k1x_pcie *k1x)
|
|
u32 val = 0;
|
|
int count;
|
|
|
|
- printk("Now init Rterm...\n");
|
|
- printk("pcie prot id = %d, porta_init_done = %d\n", k1x->port_id, porta_init_done);
|
|
+ pr_debug("Now init Rterm...\n");
|
|
+ pr_debug("pcie prot id = %d, porta_init_done = %d\n", k1x->port_id, porta_init_done);
|
|
if (k1x->port_id != 0) {
|
|
if (porta_init_done == 0) {
|
|
porta_rterm(k1x);
|
|
@@ -498,7 +495,7 @@ static int init_phy(struct k1x_pcie *k1x)
|
|
//rd_data = REG32(0xC0B10000 + 0x21 * 4);
|
|
rd_data = k1x_pcie_phy0_reg_readl(k1x, (0x21 * 4));
|
|
if (count++ > 5000) {
|
|
- printk(KERN_WARNING "read pcie0 phy rd_data time out.\n");
|
|
+ pr_err("read pcie0 phy rd_data time out.\n");
|
|
break;
|
|
}
|
|
} while (((rd_data >> 10) & 0x1) == 0);
|
|
@@ -509,7 +506,7 @@ static int init_phy(struct k1x_pcie *k1x)
|
|
k1x->pcie_rcal = pcie_rcal;
|
|
rterm_force(k1x, pcie_rcal);
|
|
|
|
- printk("Now int init_puphy...\n");
|
|
+ pr_debug("Now int init_puphy...\n");
|
|
val = k1x_pcie_readl(k1x, PCIECTRL_K1X_CONF_DEVICE_CMD);
|
|
val &= 0xbfffffff;
|
|
k1x_pcie_writel(k1x, PCIECTRL_K1X_CONF_DEVICE_CMD, val);
|
|
@@ -579,40 +576,32 @@ static int init_phy(struct k1x_pcie *k1x)
|
|
k1x_pcie_phy_reg_writel(k1x, (0x12 << 2), val);
|
|
|
|
// PU_ADDR_CLK_CFG of lane0
|
|
- val = k1x_pcie_phy_reg_readl(k1x, (0x02 << 2));
|
|
val = 0x00000B78;
|
|
k1x_pcie_phy_reg_writel(k1x, (0x02 << 2), val);
|
|
|
|
// PU_ADDR_CLK_CFG of lane1
|
|
- val = k1x_pcie_phy_reg_readl(k1x, 0x400 + (0x02 << 2));
|
|
val = 0x00000B78;
|
|
k1x_pcie_phy_reg_writel(k1x, 0x400 + (0x02 << 2), val);
|
|
|
|
// force rcv done
|
|
- val = k1x_pcie_phy_reg_readl(k1x, (0x06 << 2));
|
|
val = 0x00000400;
|
|
k1x_pcie_phy_reg_writel(k1x, (0x06 << 2), val);
|
|
|
|
- // force rcv done
|
|
- val = k1x_pcie_phy_reg_readl(k1x, 0x400 + (0x06 << 2));
|
|
- val = 0x00000400;
|
|
- k1x_pcie_phy_reg_writel(k1x, 0x400 + (0x06 << 2), val);
|
|
-
|
|
// waiting pll lock
|
|
- printk("waiting pll lock...\n");
|
|
+ pr_debug("waiting pll lock...\n");
|
|
count = 0;
|
|
do
|
|
{
|
|
rd_data = k1x_pcie_phy_reg_readl(k1x, 0x8);
|
|
if (count++ > 5000) {
|
|
- printk(KERN_WARNING "read pcie%d phy rd_data time out.\n", k1x->port_id);
|
|
+ pr_err("read pcie%d phy rd_data time out.\n", k1x->port_id);
|
|
break;
|
|
}
|
|
} while ((rd_data & 0x1) == 0);
|
|
|
|
if (k1x->port_id == 0)
|
|
porta_init_done = 0x1;
|
|
- printk("Now finish init_puphy....\n");
|
|
+ pr_debug("Now finish init_puphy....\n");
|
|
return 0;
|
|
}
|
|
|
|
@@ -669,7 +658,7 @@ static int k1x_pcie_establish_link(struct dw_pcie *pci)
|
|
reg &= ~APP_HOLD_PHY_RST;
|
|
k1x_pcie_writel(k1x, PCIECTRL_K1X_CONF_DEVICE_CMD, reg);
|
|
|
|
- printk("ltssm enable\n");
|
|
+ pr_debug("ltssm enable\n");
|
|
return 0;
|
|
}
|
|
|
|
@@ -864,7 +853,7 @@ void k1x_pcie_msix_addr_alloc(struct dw_pcie_rp *pp)
|
|
}
|
|
msi_target = (u64)k1x->msix_addr;
|
|
|
|
- pr_info("(u64)pp->msix_addr =%llx\n", (u64)k1x->msix_addr);
|
|
+ pr_debug("(u64)pp->msix_addr =%llx\n", (u64)k1x->msix_addr);
|
|
reg = k1x_pcie_phy_ahb_readl(k1x, ADDR_MSI_RECV_CTRL);
|
|
reg |= MSIX_MON_EN;
|
|
k1x_pcie_phy_ahb_writel(k1x, ADDR_MSI_RECV_CTRL, reg);
|
|
@@ -893,7 +882,7 @@ void k1x_pcie_msi_addr_alloc(struct dw_pcie_rp *pp)
|
|
}
|
|
msi_target = (u64)pp->msi_data;
|
|
|
|
- pr_info("(u64)pp->msi_data =%llx\n", (u64)pp->msi_data);
|
|
+ pr_debug("(u64)pp->msi_data =%llx\n", (u64)pp->msi_data);
|
|
/* Program the msi_data */
|
|
dw_pcie_writel_dbi(pci, PCIE_MSI_ADDR_LO, lower_32_bits(msi_target));
|
|
dw_pcie_writel_dbi(pci, PCIE_MSI_ADDR_HI, upper_32_bits(msi_target));
|
|
@@ -1017,7 +1006,7 @@ static int k1x_pcie_host_init(struct dw_pcie_rp *pp)
|
|
|
|
/* read the link status register, get the current speed */
|
|
reg = dw_pcie_readw_dbi(pci, EXP_CAP_ID_OFFSET + PCI_EXP_LNKSTA);
|
|
- pr_info("Link up, Gen%i\n", reg & PCI_EXP_LNKSTA_CLS);
|
|
+ pr_debug("Link up, Gen%i\n", reg & PCI_EXP_LNKSTA_CLS);
|
|
|
|
k1x_pcie_enable_msi_interrupts(k1x);
|
|
|
|
@@ -1396,7 +1385,7 @@ static int k1x_pcie_enable_phy(struct k1x_pcie *k1x)
|
|
u32 reg, val, rd_data;
|
|
int count;
|
|
|
|
- printk("Now k1x_pcie_enable_phy in resume...\n");
|
|
+ pr_debug("Now k1x_pcie_enable_phy in resume...\n");
|
|
|
|
reg = k1x_pcie_readl(k1x, PCIECTRL_K1X_CONF_DEVICE_CMD);
|
|
reg |= 0x3f;
|
|
@@ -1473,38 +1462,30 @@ static int k1x_pcie_enable_phy(struct k1x_pcie *k1x)
|
|
k1x_pcie_phy_reg_writel(k1x, (0x12 << 2), val);
|
|
|
|
// PU_ADDR_CLK_CFG of lane0
|
|
- val = k1x_pcie_phy_reg_readl(k1x, (0x02 << 2));
|
|
val = 0x00000B78;
|
|
k1x_pcie_phy_reg_writel(k1x, (0x02 << 2), val);
|
|
|
|
// PU_ADDR_CLK_CFG of lane1
|
|
- val = k1x_pcie_phy_reg_readl(k1x, 0x400 + (0x02 << 2));
|
|
val = 0x00000B78;
|
|
k1x_pcie_phy_reg_writel(k1x, 0x400 + (0x02 << 2), val);
|
|
|
|
// force rcv done
|
|
- val = k1x_pcie_phy_reg_readl(k1x, (0x06 << 2));
|
|
val = 0x00000400;
|
|
k1x_pcie_phy_reg_writel(k1x, (0x06 << 2), val);
|
|
|
|
- // force rcv done
|
|
- val = k1x_pcie_phy_reg_readl(k1x, 0x400 + (0x06 << 2));
|
|
- val = 0x00000400;
|
|
- k1x_pcie_phy_reg_writel(k1x, 0x400 + (0x06 << 2), val);
|
|
-
|
|
// waiting pll lock
|
|
- printk("waiting pll lock...\n");
|
|
+ pr_debug("waiting pll lock...\n");
|
|
count = 0;
|
|
do
|
|
{
|
|
rd_data = k1x_pcie_phy_reg_readl(k1x, 0x8);
|
|
if (count++ > 5000) {
|
|
- printk(KERN_WARNING "read pcie%d phy rd_data time out.\n", k1x->port_id);
|
|
+ pr_err("read pcie%d phy rd_data time out.\n", k1x->port_id);
|
|
break;
|
|
}
|
|
} while ((rd_data & 0x1) == 0);
|
|
|
|
- printk("Now finish enable phy....\n");
|
|
+ pr_debug("Now finish enable phy....\n");
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/regulator/spacemit-regulator.c b/drivers/regulator/spacemit-regulator.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/regulator/spacemit-regulator.c
|
|
+++ b/drivers/regulator/spacemit-regulator.c
|
|
@@ -17,6 +17,31 @@
|
|
#include <linux/gpio/consumer.h>
|
|
#include <linux/mfd/spacemit/spacemit_pmic.h>
|
|
|
|
+static struct regulator_match_data *match_data;
|
|
+
|
|
+static int spacemit_regulator_set_suspend_voltage(struct regulator_dev *rdev, int uV)
|
|
+{
|
|
+ unsigned int reg;
|
|
+
|
|
+ int sel = regulator_map_voltage_linear_range(rdev, uV, uV);
|
|
+
|
|
+ if (sel < 0)
|
|
+ return -EINVAL;
|
|
+
|
|
+ /* means that we will disable this vol in suspend */
|
|
+ if (uV == rdev->constraints->max_uV)
|
|
+ /* BUCK will set 0xff to close the power */
|
|
+ sel = rdev->desc->vsel_mask;
|
|
+ else if (uV == rdev->constraints->min_uV)
|
|
+ /* LDO will set zero to close the power */
|
|
+ sel = 0;
|
|
+
|
|
+ reg = rdev->desc->vsel_reg + match_data->sleep_reg_offset;
|
|
+
|
|
+ return regmap_update_bits(rdev->regmap, reg,
|
|
+ rdev->desc->vsel_mask, sel);
|
|
+}
|
|
+
|
|
static const struct regulator_ops pmic_dcdc_ldo_ops = {
|
|
.list_voltage = regulator_list_voltage_linear_range,
|
|
.map_voltage = regulator_map_voltage_linear_range,
|
|
@@ -26,6 +51,7 @@ static const struct regulator_ops pmic_dcdc_ldo_ops = {
|
|
.enable = regulator_enable_regmap,
|
|
.disable = regulator_disable_regmap,
|
|
.is_enabled = regulator_is_enabled_regmap,
|
|
+ .set_suspend_voltage = spacemit_regulator_set_suspend_voltage,
|
|
};
|
|
|
|
static const struct regulator_ops pmic_switch_ops = {
|
|
@@ -57,7 +83,6 @@ static int spacemit_regulator_probe(struct platform_device *pdev)
|
|
struct spacemit_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
|
|
struct i2c_client *client;
|
|
const struct of_device_id *of_id;
|
|
- struct regulator_match_data *match_data;
|
|
struct regulator_dev *regulator_dev;
|
|
int i;
|
|
|
|
diff --git a/drivers/remoteproc/k1x-rproc.c b/drivers/remoteproc/k1x-rproc.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/remoteproc/k1x-rproc.c
|
|
+++ b/drivers/remoteproc/k1x-rproc.c
|
|
@@ -619,12 +619,16 @@ static int spacemit_rproc_probe(struct platform_device *pdev)
|
|
register_platform_pm_ops(&rproc_platform_pm_ops);
|
|
#endif
|
|
|
|
- rproc->auto_boot = true;
|
|
ret = devm_rproc_add(dev, rproc);
|
|
if (ret) {
|
|
dev_err(dev, "rproc_add failed\n");
|
|
}
|
|
|
|
+ ret = rproc_boot(rproc);
|
|
+ if (ret) {
|
|
+ dev_err(dev, "rproc_boot failed\n");
|
|
+ }
|
|
+
|
|
return ret;
|
|
}
|
|
|
|
@@ -656,6 +660,7 @@ static int spacemit_rproc_remove(struct platform_device *pdev)
|
|
|
|
#ifdef CONFIG_PM_SLEEP
|
|
unregister_rpmsg_driver(&rpmsg_rcpu_pm_client);
|
|
+ unregister_platform_pm_ops(&rproc_platform_pm_ops);
|
|
#endif
|
|
return 0;
|
|
}
|
|
@@ -700,7 +705,7 @@ static __init int spacemit_rproc_driver_init(void)
|
|
{
|
|
return platform_driver_register(&spacemit_rproc_driver);
|
|
}
|
|
-subsys_initcall(spacemit_rproc_driver_init);
|
|
+device_initcall(spacemit_rproc_driver_init);
|
|
|
|
MODULE_LICENSE("GPL v2");
|
|
MODULE_DESCRIPTION("sapcemit remote processor control driver");
|
|
diff --git a/drivers/soc/spacemit/jpu/jpu.c b/drivers/soc/spacemit/jpu/jpu.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/soc/spacemit/jpu/jpu.c
|
|
+++ b/drivers/soc/spacemit/jpu/jpu.c
|
|
@@ -1695,7 +1695,7 @@ static int jpu_probe(struct platform_device *pdev)
|
|
cpuid = 0;
|
|
cpumask_set_cpu(cpuid, &mask);
|
|
irq_set_affinity(jdev->s_jpu_irq, &mask);
|
|
- dev_notice(jdev->jdev, "driver probe successfully\n");
|
|
+ dev_dbg(jdev->jdev, "driver probe successfully\n");
|
|
return 0;
|
|
err0:
|
|
return -1;
|
|
@@ -1730,7 +1730,7 @@ static int jpu_remove(struct platform_device *pdev)
|
|
#endif
|
|
sysfs_remove_groups(&pdev->dev.kobj, jpu_frequency_group);
|
|
|
|
- dev_notice(jdev->jdev, "driver removed\n");
|
|
+ dev_dbg(jdev->jdev, "driver removed\n");
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/soc/spacemit/pm_domain/k1x-pm_domain.c b/drivers/soc/spacemit/pm_domain/k1x-pm_domain.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/soc/spacemit/pm_domain/k1x-pm_domain.c
|
|
+++ b/drivers/soc/spacemit/pm_domain/k1x-pm_domain.c
|
|
@@ -473,8 +473,9 @@ static void spacemit_pd_detach_dev(struct generic_pm_domain *genpd, struct devic
|
|
dev_pm_qos_remove_notifier(dev, &pos->notifier, DEV_PM_QOS_MAX_FREQUENCY);
|
|
while (--pos->rgr_count >= 0)
|
|
devm_regulator_put(pos->rgr[pos->rgr_count]);
|
|
- list_del(&pos->qos_node);
|
|
}
|
|
+
|
|
+ list_del(&pos->qos_node);
|
|
}
|
|
|
|
static int spacemit_cpuidle_qos_notfier_call(struct notifier_block *nb, unsigned long action, void *data)
|
|
diff --git a/drivers/spi/spi-k1x-qspi.c b/drivers/spi/spi-k1x-qspi.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/spi/spi-k1x-qspi.c
|
|
+++ b/drivers/spi/spi-k1x-qspi.c
|
|
@@ -1305,8 +1305,11 @@ static int k1x_qspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
|
|
if (op->data.nbytes > qspi->tx_unit_size)
|
|
op->data.nbytes = qspi->tx_unit_size;
|
|
} else {
|
|
- if (op->data.nbytes > qspi->rx_unit_size)
|
|
+ if (op->data.nbytes > qspi->rx_unit_size) {
|
|
op->data.nbytes = qspi->rx_unit_size;
|
|
+ } else if (op->data.nbytes > qspi->rx_buf_size - 4 && !IS_ALIGNED(op->data.nbytes, 4)) {
|
|
+ op->data.nbytes = qspi->rx_buf_size - 4;
|
|
+ }
|
|
}
|
|
mutex_unlock(&qspi->lock);
|
|
|
|
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/target/target_core_configfs.c
|
|
+++ b/drivers/target/target_core_configfs.c
|
|
@@ -547,6 +547,7 @@ DEF_CONFIGFS_ATTRIB_SHOW(unmap_granularity);
|
|
DEF_CONFIGFS_ATTRIB_SHOW(unmap_granularity_alignment);
|
|
DEF_CONFIGFS_ATTRIB_SHOW(unmap_zeroes_data);
|
|
DEF_CONFIGFS_ATTRIB_SHOW(max_write_same_len);
|
|
+DEF_CONFIGFS_ATTRIB_SHOW(emulate_rsoc);
|
|
|
|
#define DEF_CONFIGFS_ATTRIB_STORE_U32(_name) \
|
|
static ssize_t _name##_store(struct config_item *item, const char *page,\
|
|
@@ -1186,6 +1187,23 @@ static ssize_t pgr_support_store(struct config_item *item,
|
|
return count;
|
|
}
|
|
|
|
+static ssize_t emulate_rsoc_store(struct config_item *item,
|
|
+ const char *page, size_t count)
|
|
+{
|
|
+ struct se_dev_attrib *da = to_attrib(item);
|
|
+ bool flag;
|
|
+ int ret;
|
|
+
|
|
+ ret = strtobool(page, &flag);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ da->emulate_rsoc = flag;
|
|
+ pr_debug("dev[%p]: SE Device REPORT_SUPPORTED_OPERATION_CODES_EMULATION flag: %d\n",
|
|
+ da->da_dev, flag);
|
|
+ return count;
|
|
+}
|
|
+
|
|
CONFIGFS_ATTR(, emulate_model_alias);
|
|
CONFIGFS_ATTR(, emulate_dpo);
|
|
CONFIGFS_ATTR(, emulate_fua_write);
|
|
@@ -1198,6 +1216,7 @@ CONFIGFS_ATTR(, emulate_tpws);
|
|
CONFIGFS_ATTR(, emulate_caw);
|
|
CONFIGFS_ATTR(, emulate_3pc);
|
|
CONFIGFS_ATTR(, emulate_pr);
|
|
+CONFIGFS_ATTR(, emulate_rsoc);
|
|
CONFIGFS_ATTR(, pi_prot_type);
|
|
CONFIGFS_ATTR_RO(, hw_pi_prot_type);
|
|
CONFIGFS_ATTR(, pi_prot_format);
|
|
@@ -1261,6 +1280,7 @@ struct configfs_attribute *sbc_attrib_attrs[] = {
|
|
&attr_max_write_same_len,
|
|
&attr_alua_support,
|
|
&attr_pgr_support,
|
|
+ &attr_emulate_rsoc,
|
|
NULL,
|
|
};
|
|
EXPORT_SYMBOL(sbc_attrib_attrs);
|
|
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/target/target_core_spc.c
|
|
+++ b/drivers/target/target_core_spc.c
|
|
@@ -1314,6 +1314,922 @@ spc_emulate_testunitready(struct se_cmd *cmd)
|
|
return 0;
|
|
}
|
|
|
|
+static void set_dpofua_usage_bits(u8 *usage_bits, struct se_device *dev)
|
|
+{
|
|
+ if (!target_check_fua(dev))
|
|
+ usage_bits[1] &= ~0x18;
|
|
+ else
|
|
+ usage_bits[1] |= 0x18;
|
|
+}
|
|
+
|
|
+static void set_dpofua_usage_bits32(u8 *usage_bits, struct se_device *dev)
|
|
+{
|
|
+ if (!target_check_fua(dev))
|
|
+ usage_bits[10] &= ~0x18;
|
|
+ else
|
|
+ usage_bits[10] |= 0x18;
|
|
+}
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_read6 = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = READ_6,
|
|
+ .cdb_size = 6,
|
|
+ .usage_bits = {READ_6, 0x1f, 0xff, 0xff,
|
|
+ 0xff, SCSI_CONTROL_MASK},
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_read10 = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = READ_10,
|
|
+ .cdb_size = 10,
|
|
+ .usage_bits = {READ_10, 0xf8, 0xff, 0xff,
|
|
+ 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, 0xff,
|
|
+ 0xff, SCSI_CONTROL_MASK},
|
|
+ .update_usage_bits = set_dpofua_usage_bits,
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_read12 = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = READ_12,
|
|
+ .cdb_size = 12,
|
|
+ .usage_bits = {READ_12, 0xf8, 0xff, 0xff,
|
|
+ 0xff, 0xff, 0xff, 0xff,
|
|
+ 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK},
|
|
+ .update_usage_bits = set_dpofua_usage_bits,
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_read16 = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = READ_16,
|
|
+ .cdb_size = 16,
|
|
+ .usage_bits = {READ_16, 0xf8, 0xff, 0xff,
|
|
+ 0xff, 0xff, 0xff, 0xff,
|
|
+ 0xff, 0xff, 0xff, 0xff,
|
|
+ 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK},
|
|
+ .update_usage_bits = set_dpofua_usage_bits,
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_write6 = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = WRITE_6,
|
|
+ .cdb_size = 6,
|
|
+ .usage_bits = {WRITE_6, 0x1f, 0xff, 0xff,
|
|
+ 0xff, SCSI_CONTROL_MASK},
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_write10 = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = WRITE_10,
|
|
+ .cdb_size = 10,
|
|
+ .usage_bits = {WRITE_10, 0xf8, 0xff, 0xff,
|
|
+ 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, 0xff,
|
|
+ 0xff, SCSI_CONTROL_MASK},
|
|
+ .update_usage_bits = set_dpofua_usage_bits,
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_write_verify10 = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = WRITE_VERIFY,
|
|
+ .cdb_size = 10,
|
|
+ .usage_bits = {WRITE_VERIFY, 0xf0, 0xff, 0xff,
|
|
+ 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, 0xff,
|
|
+ 0xff, SCSI_CONTROL_MASK},
|
|
+ .update_usage_bits = set_dpofua_usage_bits,
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_write12 = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = WRITE_12,
|
|
+ .cdb_size = 12,
|
|
+ .usage_bits = {WRITE_12, 0xf8, 0xff, 0xff,
|
|
+ 0xff, 0xff, 0xff, 0xff,
|
|
+ 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK},
|
|
+ .update_usage_bits = set_dpofua_usage_bits,
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_write16 = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = WRITE_16,
|
|
+ .cdb_size = 16,
|
|
+ .usage_bits = {WRITE_16, 0xf8, 0xff, 0xff,
|
|
+ 0xff, 0xff, 0xff, 0xff,
|
|
+ 0xff, 0xff, 0xff, 0xff,
|
|
+ 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK},
|
|
+ .update_usage_bits = set_dpofua_usage_bits,
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_write_verify16 = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = WRITE_VERIFY_16,
|
|
+ .cdb_size = 16,
|
|
+ .usage_bits = {WRITE_VERIFY_16, 0xf0, 0xff, 0xff,
|
|
+ 0xff, 0xff, 0xff, 0xff,
|
|
+ 0xff, 0xff, 0xff, 0xff,
|
|
+ 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK},
|
|
+ .update_usage_bits = set_dpofua_usage_bits,
|
|
+};
|
|
+
|
|
+static bool tcm_is_ws_enabled(struct se_cmd *cmd)
|
|
+{
|
|
+ struct sbc_ops *ops = cmd->protocol_data;
|
|
+ struct se_device *dev = cmd->se_dev;
|
|
+
|
|
+ return (dev->dev_attrib.emulate_tpws && !!ops->execute_unmap) ||
|
|
+ !!ops->execute_write_same;
|
|
+}
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_write_same32 = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .serv_action_valid = 1,
|
|
+ .opcode = VARIABLE_LENGTH_CMD,
|
|
+ .service_action = WRITE_SAME_32,
|
|
+ .cdb_size = 32,
|
|
+ .usage_bits = {VARIABLE_LENGTH_CMD, SCSI_CONTROL_MASK, 0x00, 0x00,
|
|
+ 0x00, 0x00, SCSI_GROUP_NUMBER_MASK, 0x18,
|
|
+ 0x00, WRITE_SAME_32, 0xe8, 0x00,
|
|
+ 0xff, 0xff, 0xff, 0xff,
|
|
+ 0xff, 0xff, 0xff, 0xff,
|
|
+ 0x00, 0x00, 0x00, 0x00,
|
|
+ 0x00, 0x00, 0x00, 0x00,
|
|
+ 0xff, 0xff, 0xff, 0xff},
|
|
+ .enabled = tcm_is_ws_enabled,
|
|
+ .update_usage_bits = set_dpofua_usage_bits32,
|
|
+};
|
|
+
|
|
+static bool tcm_is_caw_enabled(struct se_cmd *cmd)
|
|
+{
|
|
+ struct se_device *dev = cmd->se_dev;
|
|
+
|
|
+ return dev->dev_attrib.emulate_caw;
|
|
+}
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_compare_write = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = COMPARE_AND_WRITE,
|
|
+ .cdb_size = 16,
|
|
+ .usage_bits = {COMPARE_AND_WRITE, 0x18, 0xff, 0xff,
|
|
+ 0xff, 0xff, 0xff, 0xff,
|
|
+ 0xff, 0xff, 0x00, 0x00,
|
|
+ 0x00, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK},
|
|
+ .enabled = tcm_is_caw_enabled,
|
|
+ .update_usage_bits = set_dpofua_usage_bits,
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_read_capacity = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = READ_CAPACITY,
|
|
+ .cdb_size = 10,
|
|
+ .usage_bits = {READ_CAPACITY, 0x00, 0xff, 0xff,
|
|
+ 0xff, 0xff, 0x00, 0x00,
|
|
+ 0x01, SCSI_CONTROL_MASK},
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_read_capacity16 = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .serv_action_valid = 1,
|
|
+ .opcode = SERVICE_ACTION_IN_16,
|
|
+ .service_action = SAI_READ_CAPACITY_16,
|
|
+ .cdb_size = 16,
|
|
+ .usage_bits = {SERVICE_ACTION_IN_16, SAI_READ_CAPACITY_16, 0x00, 0x00,
|
|
+ 0x00, 0x00, 0x00, 0x00,
|
|
+ 0x00, 0x00, 0xff, 0xff,
|
|
+ 0xff, 0xff, 0x00, SCSI_CONTROL_MASK},
|
|
+};
|
|
+
|
|
+static bool tcm_is_rep_ref_enabled(struct se_cmd *cmd)
|
|
+{
|
|
+ struct se_device *dev = cmd->se_dev;
|
|
+
|
|
+ spin_lock(&dev->t10_alua.lba_map_lock);
|
|
+ if (list_empty(&dev->t10_alua.lba_map_list)) {
|
|
+ spin_unlock(&dev->t10_alua.lba_map_lock);
|
|
+ return false;
|
|
+ }
|
|
+ spin_unlock(&dev->t10_alua.lba_map_lock);
|
|
+ return true;
|
|
+
|
|
+}
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_read_report_refferals = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .serv_action_valid = 1,
|
|
+ .opcode = SERVICE_ACTION_IN_16,
|
|
+ .service_action = SAI_REPORT_REFERRALS,
|
|
+ .cdb_size = 16,
|
|
+ .usage_bits = {SERVICE_ACTION_IN_16, SAI_REPORT_REFERRALS, 0x00, 0x00,
|
|
+ 0x00, 0x00, 0x00, 0x00,
|
|
+ 0x00, 0x00, 0xff, 0xff,
|
|
+ 0xff, 0xff, 0x00, SCSI_CONTROL_MASK},
|
|
+ .enabled = tcm_is_rep_ref_enabled,
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_sync_cache = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = SYNCHRONIZE_CACHE,
|
|
+ .cdb_size = 10,
|
|
+ .usage_bits = {SYNCHRONIZE_CACHE, 0x02, 0xff, 0xff,
|
|
+ 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, 0xff,
|
|
+ 0xff, SCSI_CONTROL_MASK},
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_sync_cache16 = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = SYNCHRONIZE_CACHE_16,
|
|
+ .cdb_size = 16,
|
|
+ .usage_bits = {SYNCHRONIZE_CACHE_16, 0x02, 0xff, 0xff,
|
|
+ 0xff, 0xff, 0xff, 0xff,
|
|
+ 0xff, 0xff, 0xff, 0xff,
|
|
+ 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK},
|
|
+};
|
|
+
|
|
+static bool tcm_is_unmap_enabled(struct se_cmd *cmd)
|
|
+{
|
|
+ struct sbc_ops *ops = cmd->protocol_data;
|
|
+ struct se_device *dev = cmd->se_dev;
|
|
+
|
|
+ return ops->execute_unmap && dev->dev_attrib.emulate_tpu;
|
|
+}
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_unmap = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = UNMAP,
|
|
+ .cdb_size = 10,
|
|
+ .usage_bits = {UNMAP, 0x00, 0x00, 0x00,
|
|
+ 0x00, 0x00, SCSI_GROUP_NUMBER_MASK, 0xff,
|
|
+ 0xff, SCSI_CONTROL_MASK},
|
|
+ .enabled = tcm_is_unmap_enabled,
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_write_same = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = WRITE_SAME,
|
|
+ .cdb_size = 10,
|
|
+ .usage_bits = {WRITE_SAME, 0xe8, 0xff, 0xff,
|
|
+ 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, 0xff,
|
|
+ 0xff, SCSI_CONTROL_MASK},
|
|
+ .enabled = tcm_is_ws_enabled,
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_write_same16 = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = WRITE_SAME_16,
|
|
+ .cdb_size = 16,
|
|
+ .usage_bits = {WRITE_SAME_16, 0xe8, 0xff, 0xff,
|
|
+ 0xff, 0xff, 0xff, 0xff,
|
|
+ 0xff, 0xff, 0xff, 0xff,
|
|
+ 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK},
|
|
+ .enabled = tcm_is_ws_enabled,
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_verify = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = VERIFY,
|
|
+ .cdb_size = 10,
|
|
+ .usage_bits = {VERIFY, 0x00, 0xff, 0xff,
|
|
+ 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, 0xff,
|
|
+ 0xff, SCSI_CONTROL_MASK},
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_verify16 = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = VERIFY_16,
|
|
+ .cdb_size = 16,
|
|
+ .usage_bits = {VERIFY_16, 0x00, 0xff, 0xff,
|
|
+ 0xff, 0xff, 0xff, 0xff,
|
|
+ 0xff, 0xff, 0xff, 0xff,
|
|
+ 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK},
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_start_stop = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = START_STOP,
|
|
+ .cdb_size = 6,
|
|
+ .usage_bits = {START_STOP, 0x01, 0x00, 0x00,
|
|
+ 0x01, SCSI_CONTROL_MASK},
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_mode_select = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = MODE_SELECT,
|
|
+ .cdb_size = 6,
|
|
+ .usage_bits = {MODE_SELECT, 0x10, 0x00, 0x00,
|
|
+ 0xff, SCSI_CONTROL_MASK},
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_mode_select10 = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = MODE_SELECT_10,
|
|
+ .cdb_size = 10,
|
|
+ .usage_bits = {MODE_SELECT_10, 0x10, 0x00, 0x00,
|
|
+ 0x00, 0x00, 0x00, 0xff,
|
|
+ 0xff, SCSI_CONTROL_MASK},
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_mode_sense = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = MODE_SENSE,
|
|
+ .cdb_size = 6,
|
|
+ .usage_bits = {MODE_SENSE, 0x08, 0xff, 0xff,
|
|
+ 0xff, SCSI_CONTROL_MASK},
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_mode_sense10 = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = MODE_SENSE_10,
|
|
+ .cdb_size = 10,
|
|
+ .usage_bits = {MODE_SENSE_10, 0x18, 0xff, 0xff,
|
|
+ 0x00, 0x00, 0x00, 0xff,
|
|
+ 0xff, SCSI_CONTROL_MASK},
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_pri_read_keys = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .serv_action_valid = 1,
|
|
+ .opcode = PERSISTENT_RESERVE_IN,
|
|
+ .service_action = PRI_READ_KEYS,
|
|
+ .cdb_size = 10,
|
|
+ .usage_bits = {PERSISTENT_RESERVE_IN, PRI_READ_KEYS, 0x00, 0x00,
|
|
+ 0x00, 0x00, 0x00, 0xff,
|
|
+ 0xff, SCSI_CONTROL_MASK},
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_pri_read_resrv = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .serv_action_valid = 1,
|
|
+ .opcode = PERSISTENT_RESERVE_IN,
|
|
+ .service_action = PRI_READ_RESERVATION,
|
|
+ .cdb_size = 10,
|
|
+ .usage_bits = {PERSISTENT_RESERVE_IN, PRI_READ_RESERVATION, 0x00, 0x00,
|
|
+ 0x00, 0x00, 0x00, 0xff,
|
|
+ 0xff, SCSI_CONTROL_MASK},
|
|
+};
|
|
+
|
|
+static bool tcm_is_pr_enabled(struct se_cmd *cmd)
|
|
+{
|
|
+ struct se_device *dev = cmd->se_dev;
|
|
+
|
|
+ return dev->dev_attrib.emulate_pr;
|
|
+}
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_pri_read_caps = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .serv_action_valid = 1,
|
|
+ .opcode = PERSISTENT_RESERVE_IN,
|
|
+ .service_action = PRI_REPORT_CAPABILITIES,
|
|
+ .cdb_size = 10,
|
|
+ .usage_bits = {PERSISTENT_RESERVE_IN, PRI_REPORT_CAPABILITIES, 0x00, 0x00,
|
|
+ 0x00, 0x00, 0x00, 0xff,
|
|
+ 0xff, SCSI_CONTROL_MASK},
|
|
+ .enabled = tcm_is_pr_enabled,
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_pri_read_full_status = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .serv_action_valid = 1,
|
|
+ .opcode = PERSISTENT_RESERVE_IN,
|
|
+ .service_action = PRI_READ_FULL_STATUS,
|
|
+ .cdb_size = 10,
|
|
+ .usage_bits = {PERSISTENT_RESERVE_IN, PRI_READ_FULL_STATUS, 0x00, 0x00,
|
|
+ 0x00, 0x00, 0x00, 0xff,
|
|
+ 0xff, SCSI_CONTROL_MASK},
|
|
+ .enabled = tcm_is_pr_enabled,
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_pro_register = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .serv_action_valid = 1,
|
|
+ .opcode = PERSISTENT_RESERVE_OUT,
|
|
+ .service_action = PRO_REGISTER,
|
|
+ .cdb_size = 10,
|
|
+ .usage_bits = {PERSISTENT_RESERVE_OUT, PRO_REGISTER, 0xff, 0x00,
|
|
+ 0x00, 0xff, 0xff, 0xff,
|
|
+ 0xff, SCSI_CONTROL_MASK},
|
|
+ .enabled = tcm_is_pr_enabled,
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_pro_reserve = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .serv_action_valid = 1,
|
|
+ .opcode = PERSISTENT_RESERVE_OUT,
|
|
+ .service_action = PRO_RESERVE,
|
|
+ .cdb_size = 10,
|
|
+ .usage_bits = {PERSISTENT_RESERVE_OUT, PRO_RESERVE, 0xff, 0x00,
|
|
+ 0x00, 0xff, 0xff, 0xff,
|
|
+ 0xff, SCSI_CONTROL_MASK},
|
|
+ .enabled = tcm_is_pr_enabled,
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_pro_release = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .serv_action_valid = 1,
|
|
+ .opcode = PERSISTENT_RESERVE_OUT,
|
|
+ .service_action = PRO_RELEASE,
|
|
+ .cdb_size = 10,
|
|
+ .usage_bits = {PERSISTENT_RESERVE_OUT, PRO_RELEASE, 0xff, 0x00,
|
|
+ 0x00, 0xff, 0xff, 0xff,
|
|
+ 0xff, SCSI_CONTROL_MASK},
|
|
+ .enabled = tcm_is_pr_enabled,
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_pro_clear = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .serv_action_valid = 1,
|
|
+ .opcode = PERSISTENT_RESERVE_OUT,
|
|
+ .service_action = PRO_CLEAR,
|
|
+ .cdb_size = 10,
|
|
+ .usage_bits = {PERSISTENT_RESERVE_OUT, PRO_CLEAR, 0xff, 0x00,
|
|
+ 0x00, 0xff, 0xff, 0xff,
|
|
+ 0xff, SCSI_CONTROL_MASK},
|
|
+ .enabled = tcm_is_pr_enabled,
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_pro_preempt = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .serv_action_valid = 1,
|
|
+ .opcode = PERSISTENT_RESERVE_OUT,
|
|
+ .service_action = PRO_PREEMPT,
|
|
+ .cdb_size = 10,
|
|
+ .usage_bits = {PERSISTENT_RESERVE_OUT, PRO_PREEMPT, 0xff, 0x00,
|
|
+ 0x00, 0xff, 0xff, 0xff,
|
|
+ 0xff, SCSI_CONTROL_MASK},
|
|
+ .enabled = tcm_is_pr_enabled,
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_pro_preempt_abort = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .serv_action_valid = 1,
|
|
+ .opcode = PERSISTENT_RESERVE_OUT,
|
|
+ .service_action = PRO_PREEMPT_AND_ABORT,
|
|
+ .cdb_size = 10,
|
|
+ .usage_bits = {PERSISTENT_RESERVE_OUT, PRO_PREEMPT_AND_ABORT, 0xff, 0x00,
|
|
+ 0x00, 0xff, 0xff, 0xff,
|
|
+ 0xff, SCSI_CONTROL_MASK},
|
|
+ .enabled = tcm_is_pr_enabled,
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_pro_reg_ign_exist = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .serv_action_valid = 1,
|
|
+ .opcode = PERSISTENT_RESERVE_OUT,
|
|
+ .service_action = PRO_REGISTER_AND_IGNORE_EXISTING_KEY,
|
|
+ .cdb_size = 10,
|
|
+ .usage_bits = {
|
|
+ PERSISTENT_RESERVE_OUT, PRO_REGISTER_AND_IGNORE_EXISTING_KEY,
|
|
+ 0xff, 0x00,
|
|
+ 0x00, 0xff, 0xff, 0xff,
|
|
+ 0xff, SCSI_CONTROL_MASK},
|
|
+ .enabled = tcm_is_pr_enabled,
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_pro_register_move = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .serv_action_valid = 1,
|
|
+ .opcode = PERSISTENT_RESERVE_OUT,
|
|
+ .service_action = PRO_REGISTER_AND_MOVE,
|
|
+ .cdb_size = 10,
|
|
+ .usage_bits = {PERSISTENT_RESERVE_OUT, PRO_REGISTER_AND_MOVE, 0xff, 0x00,
|
|
+ 0x00, 0xff, 0xff, 0xff,
|
|
+ 0xff, SCSI_CONTROL_MASK},
|
|
+ .enabled = tcm_is_pr_enabled,
|
|
+};
|
|
+
|
|
+static bool tcm_is_scsi2_reservations_enabled(struct se_cmd *cmd)
|
|
+{
|
|
+ struct se_device *dev = cmd->se_dev;
|
|
+
|
|
+ return dev->dev_attrib.emulate_pr;
|
|
+}
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_release = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = RELEASE,
|
|
+ .cdb_size = 6,
|
|
+ .usage_bits = {RELEASE, 0x00, 0x00, 0x00,
|
|
+ 0x00, SCSI_CONTROL_MASK},
|
|
+ .enabled = tcm_is_scsi2_reservations_enabled,
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_release10 = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = RELEASE_10,
|
|
+ .cdb_size = 10,
|
|
+ .usage_bits = {RELEASE_10, 0x00, 0x00, 0x00,
|
|
+ 0x00, 0x00, 0x00, 0xff,
|
|
+ 0xff, SCSI_CONTROL_MASK},
|
|
+ .enabled = tcm_is_scsi2_reservations_enabled,
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_reserve = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = RESERVE,
|
|
+ .cdb_size = 6,
|
|
+ .usage_bits = {RESERVE, 0x00, 0x00, 0x00,
|
|
+ 0x00, SCSI_CONTROL_MASK},
|
|
+ .enabled = tcm_is_scsi2_reservations_enabled,
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_reserve10 = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = RESERVE_10,
|
|
+ .cdb_size = 10,
|
|
+ .usage_bits = {RESERVE_10, 0x00, 0x00, 0x00,
|
|
+ 0x00, 0x00, 0x00, 0xff,
|
|
+ 0xff, SCSI_CONTROL_MASK},
|
|
+ .enabled = tcm_is_scsi2_reservations_enabled,
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_request_sense = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = REQUEST_SENSE,
|
|
+ .cdb_size = 6,
|
|
+ .usage_bits = {REQUEST_SENSE, 0x00, 0x00, 0x00,
|
|
+ 0xff, SCSI_CONTROL_MASK},
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_inquiry = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = INQUIRY,
|
|
+ .cdb_size = 6,
|
|
+ .usage_bits = {INQUIRY, 0x01, 0xff, 0xff,
|
|
+ 0xff, SCSI_CONTROL_MASK},
|
|
+};
|
|
+
|
|
+static bool tcm_is_3pc_enabled(struct se_cmd *cmd)
|
|
+{
|
|
+ struct se_device *dev = cmd->se_dev;
|
|
+
|
|
+ return dev->dev_attrib.emulate_3pc;
|
|
+}
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_extended_copy_lid1 = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .serv_action_valid = 1,
|
|
+ .opcode = EXTENDED_COPY,
|
|
+ .cdb_size = 16,
|
|
+ .usage_bits = {EXTENDED_COPY, 0x00, 0x00, 0x00,
|
|
+ 0x00, 0x00, 0x00, 0x00,
|
|
+ 0x00, 0x00, 0xff, 0xff,
|
|
+ 0xff, 0xff, 0x00, SCSI_CONTROL_MASK},
|
|
+ .enabled = tcm_is_3pc_enabled,
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_rcv_copy_res_op_params = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .serv_action_valid = 1,
|
|
+ .opcode = RECEIVE_COPY_RESULTS,
|
|
+ .service_action = RCR_SA_OPERATING_PARAMETERS,
|
|
+ .cdb_size = 16,
|
|
+ .usage_bits = {RECEIVE_COPY_RESULTS, RCR_SA_OPERATING_PARAMETERS,
|
|
+ 0x00, 0x00,
|
|
+ 0x00, 0x00, 0x00, 0x00,
|
|
+ 0x00, 0x00, 0xff, 0xff,
|
|
+ 0xff, 0xff, 0x00, SCSI_CONTROL_MASK},
|
|
+ .enabled = tcm_is_3pc_enabled,
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_report_luns = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = REPORT_LUNS,
|
|
+ .cdb_size = 12,
|
|
+ .usage_bits = {REPORT_LUNS, 0x00, 0xff, 0x00,
|
|
+ 0x00, 0x00, 0xff, 0xff,
|
|
+ 0xff, 0xff, 0x00, SCSI_CONTROL_MASK},
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_test_unit_ready = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .opcode = TEST_UNIT_READY,
|
|
+ .cdb_size = 6,
|
|
+ .usage_bits = {TEST_UNIT_READY, 0x00, 0x00, 0x00,
|
|
+ 0x00, SCSI_CONTROL_MASK},
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_report_target_pgs = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .serv_action_valid = 1,
|
|
+ .opcode = MAINTENANCE_IN,
|
|
+ .service_action = MI_REPORT_TARGET_PGS,
|
|
+ .cdb_size = 12,
|
|
+ .usage_bits = {MAINTENANCE_IN, 0xE0 | MI_REPORT_TARGET_PGS, 0x00, 0x00,
|
|
+ 0x00, 0x00, 0xff, 0xff,
|
|
+ 0xff, 0xff, 0x00, SCSI_CONTROL_MASK},
|
|
+};
|
|
+
|
|
+
|
|
+static bool spc_rsoc_enabled(struct se_cmd *cmd)
|
|
+{
|
|
+ struct se_device *dev = cmd->se_dev;
|
|
+
|
|
+ return dev->dev_attrib.emulate_rsoc;
|
|
+}
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_report_supp_opcodes = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .serv_action_valid = 1,
|
|
+ .opcode = MAINTENANCE_IN,
|
|
+ .service_action = MI_REPORT_SUPPORTED_OPERATION_CODES,
|
|
+ .cdb_size = 12,
|
|
+ .usage_bits = {MAINTENANCE_IN, MI_REPORT_SUPPORTED_OPERATION_CODES,
|
|
+ 0x87, 0xff,
|
|
+ 0xff, 0xff, 0xff, 0xff,
|
|
+ 0xff, 0xff, 0x00, SCSI_CONTROL_MASK},
|
|
+ .enabled = spc_rsoc_enabled,
|
|
+};
|
|
+
|
|
+static bool tcm_is_set_tpg_enabled(struct se_cmd *cmd)
|
|
+{
|
|
+ struct t10_alua_tg_pt_gp *l_tg_pt_gp;
|
|
+ struct se_lun *l_lun = cmd->se_lun;
|
|
+
|
|
+ rcu_read_lock();
|
|
+ l_tg_pt_gp = rcu_dereference(l_lun->lun_tg_pt_gp);
|
|
+ if (!l_tg_pt_gp) {
|
|
+ rcu_read_unlock();
|
|
+ return false;
|
|
+ }
|
|
+ if (!(l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICIT_ALUA)) {
|
|
+ rcu_read_unlock();
|
|
+ return false;
|
|
+ }
|
|
+ rcu_read_unlock();
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+static struct target_opcode_descriptor tcm_opcode_set_tpg = {
|
|
+ .support = SCSI_SUPPORT_FULL,
|
|
+ .serv_action_valid = 1,
|
|
+ .opcode = MAINTENANCE_OUT,
|
|
+ .service_action = MO_SET_TARGET_PGS,
|
|
+ .cdb_size = 12,
|
|
+ .usage_bits = {MAINTENANCE_OUT, MO_SET_TARGET_PGS, 0x00, 0x00,
|
|
+ 0x00, 0x00, 0xff, 0xff,
|
|
+ 0xff, 0xff, 0x00, SCSI_CONTROL_MASK},
|
|
+ .enabled = tcm_is_set_tpg_enabled,
|
|
+};
|
|
+
|
|
+static struct target_opcode_descriptor *tcm_supported_opcodes[] = {
|
|
+ &tcm_opcode_read6,
|
|
+ &tcm_opcode_read10,
|
|
+ &tcm_opcode_read12,
|
|
+ &tcm_opcode_read16,
|
|
+ &tcm_opcode_write6,
|
|
+ &tcm_opcode_write10,
|
|
+ &tcm_opcode_write_verify10,
|
|
+ &tcm_opcode_write12,
|
|
+ &tcm_opcode_write16,
|
|
+ &tcm_opcode_write_verify16,
|
|
+ &tcm_opcode_write_same32,
|
|
+ &tcm_opcode_compare_write,
|
|
+ &tcm_opcode_read_capacity,
|
|
+ &tcm_opcode_read_capacity16,
|
|
+ &tcm_opcode_read_report_refferals,
|
|
+ &tcm_opcode_sync_cache,
|
|
+ &tcm_opcode_sync_cache16,
|
|
+ &tcm_opcode_unmap,
|
|
+ &tcm_opcode_write_same,
|
|
+ &tcm_opcode_write_same16,
|
|
+ &tcm_opcode_verify,
|
|
+ &tcm_opcode_verify16,
|
|
+ &tcm_opcode_start_stop,
|
|
+ &tcm_opcode_mode_select,
|
|
+ &tcm_opcode_mode_select10,
|
|
+ &tcm_opcode_mode_sense,
|
|
+ &tcm_opcode_mode_sense10,
|
|
+ &tcm_opcode_pri_read_keys,
|
|
+ &tcm_opcode_pri_read_resrv,
|
|
+ &tcm_opcode_pri_read_caps,
|
|
+ &tcm_opcode_pri_read_full_status,
|
|
+ &tcm_opcode_pro_register,
|
|
+ &tcm_opcode_pro_reserve,
|
|
+ &tcm_opcode_pro_release,
|
|
+ &tcm_opcode_pro_clear,
|
|
+ &tcm_opcode_pro_preempt,
|
|
+ &tcm_opcode_pro_preempt_abort,
|
|
+ &tcm_opcode_pro_reg_ign_exist,
|
|
+ &tcm_opcode_pro_register_move,
|
|
+ &tcm_opcode_release,
|
|
+ &tcm_opcode_release10,
|
|
+ &tcm_opcode_reserve,
|
|
+ &tcm_opcode_reserve10,
|
|
+ &tcm_opcode_request_sense,
|
|
+ &tcm_opcode_inquiry,
|
|
+ &tcm_opcode_extended_copy_lid1,
|
|
+ &tcm_opcode_rcv_copy_res_op_params,
|
|
+ &tcm_opcode_report_luns,
|
|
+ &tcm_opcode_test_unit_ready,
|
|
+ &tcm_opcode_report_target_pgs,
|
|
+ &tcm_opcode_report_supp_opcodes,
|
|
+ &tcm_opcode_set_tpg,
|
|
+};
|
|
+
|
|
+static int
|
|
+spc_rsoc_encode_command_timeouts_descriptor(unsigned char *buf, u8 ctdp,
|
|
+ struct target_opcode_descriptor *descr)
|
|
+{
|
|
+ if (!ctdp)
|
|
+ return 0;
|
|
+
|
|
+ put_unaligned_be16(0xa, buf);
|
|
+ buf[3] = descr->specific_timeout;
|
|
+ put_unaligned_be32(descr->nominal_timeout, &buf[4]);
|
|
+ put_unaligned_be32(descr->recommended_timeout, &buf[8]);
|
|
+
|
|
+ return 12;
|
|
+}
|
|
+
|
|
+static int
|
|
+spc_rsoc_encode_command_descriptor(unsigned char *buf, u8 ctdp,
|
|
+ struct target_opcode_descriptor *descr)
|
|
+{
|
|
+ int td_size = 0;
|
|
+
|
|
+ buf[0] = descr->opcode;
|
|
+
|
|
+ put_unaligned_be16(descr->service_action, &buf[2]);
|
|
+
|
|
+ buf[5] = (ctdp << 1) | descr->serv_action_valid;
|
|
+ put_unaligned_be16(descr->cdb_size, &buf[6]);
|
|
+
|
|
+ td_size = spc_rsoc_encode_command_timeouts_descriptor(&buf[8], ctdp,
|
|
+ descr);
|
|
+
|
|
+ return 8 + td_size;
|
|
+}
|
|
+
|
|
+static int
|
|
+spc_rsoc_encode_one_command_descriptor(unsigned char *buf, u8 ctdp,
|
|
+ struct target_opcode_descriptor *descr,
|
|
+ struct se_device *dev)
|
|
+{
|
|
+ int td_size = 0;
|
|
+
|
|
+ if (!descr) {
|
|
+ buf[1] = (ctdp << 7) | SCSI_SUPPORT_NOT_SUPPORTED;
|
|
+ return 2;
|
|
+ }
|
|
+
|
|
+ buf[1] = (ctdp << 7) | SCSI_SUPPORT_FULL;
|
|
+ put_unaligned_be16(descr->cdb_size, &buf[2]);
|
|
+ memcpy(&buf[4], descr->usage_bits, descr->cdb_size);
|
|
+ if (descr->update_usage_bits)
|
|
+ descr->update_usage_bits(&buf[4], dev);
|
|
+
|
|
+ td_size = spc_rsoc_encode_command_timeouts_descriptor(
|
|
+ &buf[4 + descr->cdb_size], ctdp, descr);
|
|
+
|
|
+ return 4 + descr->cdb_size + td_size;
|
|
+}
|
|
+
|
|
+static sense_reason_t
|
|
+spc_rsoc_get_descr(struct se_cmd *cmd, struct target_opcode_descriptor **opcode)
|
|
+{
|
|
+ struct target_opcode_descriptor *descr;
|
|
+ struct se_session *sess = cmd->se_sess;
|
|
+ unsigned char *cdb = cmd->t_task_cdb;
|
|
+ u8 opts = cdb[2] & 0x3;
|
|
+ u8 requested_opcode;
|
|
+ u16 requested_sa;
|
|
+ int i;
|
|
+
|
|
+ requested_opcode = cdb[3];
|
|
+ requested_sa = ((u16)cdb[4]) << 8 | cdb[5];
|
|
+ *opcode = NULL;
|
|
+
|
|
+ if (opts > 3) {
|
|
+ pr_debug("TARGET_CORE[%s]: Invalid REPORT SUPPORTED OPERATION CODES"
|
|
+ " with unsupported REPORTING OPTIONS %#x for 0x%08llx from %s\n",
|
|
+ cmd->se_tfo->fabric_name, opts,
|
|
+ cmd->se_lun->unpacked_lun,
|
|
+ sess->se_node_acl->initiatorname);
|
|
+ return TCM_INVALID_CDB_FIELD;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(tcm_supported_opcodes); i++) {
|
|
+ descr = tcm_supported_opcodes[i];
|
|
+ if (descr->opcode != requested_opcode)
|
|
+ continue;
|
|
+
|
|
+ switch (opts) {
|
|
+ case 0x1:
|
|
+ /*
|
|
+ * If the REQUESTED OPERATION CODE field specifies an
|
|
+ * operation code for which the device server implements
|
|
+ * service actions, then the device server shall
|
|
+ * terminate the command with CHECK CONDITION status,
|
|
+ * with the sense key set to ILLEGAL REQUEST, and the
|
|
+ * additional sense code set to INVALID FIELD IN CDB
|
|
+ */
|
|
+ if (descr->serv_action_valid)
|
|
+ return TCM_INVALID_CDB_FIELD;
|
|
+
|
|
+ if (!descr->enabled || descr->enabled(cmd))
|
|
+ *opcode = descr;
|
|
+ break;
|
|
+ case 0x2:
|
|
+ /*
|
|
+ * If the REQUESTED OPERATION CODE field specifies an
|
|
+ * operation code for which the device server does not
|
|
+ * implement service actions, then the device server
|
|
+ * shall terminate the command with CHECK CONDITION
|
|
+ * status, with the sense key set to ILLEGAL REQUEST,
|
|
+ * and the additional sense code set to INVALID FIELD IN CDB.
|
|
+ */
|
|
+ if (descr->serv_action_valid &&
|
|
+ descr->service_action == requested_sa) {
|
|
+ if (!descr->enabled || descr->enabled(cmd))
|
|
+ *opcode = descr;
|
|
+ } else if (!descr->serv_action_valid)
|
|
+ return TCM_INVALID_CDB_FIELD;
|
|
+ break;
|
|
+ case 0x3:
|
|
+ /*
|
|
+ * The command support data for the operation code and
|
|
+ * service action a specified in the REQUESTED OPERATION
|
|
+ * CODE field and REQUESTED SERVICE ACTION field shall
|
|
+ * be returned in the one_command parameter data format.
|
|
+ */
|
|
+ if (descr->service_action == requested_sa)
|
|
+ if (!descr->enabled || descr->enabled(cmd))
|
|
+ *opcode = descr;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static sense_reason_t
|
|
+spc_emulate_report_supp_op_codes(struct se_cmd *cmd)
|
|
+{
|
|
+ int descr_num = ARRAY_SIZE(tcm_supported_opcodes);
|
|
+ struct target_opcode_descriptor *descr = NULL;
|
|
+ unsigned char *cdb = cmd->t_task_cdb;
|
|
+ u8 rctd = (cdb[2] >> 7) & 0x1;
|
|
+ unsigned char *buf = NULL;
|
|
+ int response_length = 0;
|
|
+ u8 opts = cdb[2] & 0x3;
|
|
+ unsigned char *rbuf;
|
|
+ sense_reason_t ret = 0;
|
|
+ int i;
|
|
+
|
|
+ if (!cmd->se_dev->dev_attrib.emulate_rsoc)
|
|
+ return TCM_UNSUPPORTED_SCSI_OPCODE;
|
|
+
|
|
+ rbuf = transport_kmap_data_sg(cmd);
|
|
+ if (cmd->data_length && !rbuf) {
|
|
+ ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (opts == 0)
|
|
+ response_length = 4 + (8 + rctd * 12) * descr_num;
|
|
+ else {
|
|
+ ret = spc_rsoc_get_descr(cmd, &descr);
|
|
+ if (ret)
|
|
+ goto out;
|
|
+
|
|
+ if (descr)
|
|
+ response_length = 4 + descr->cdb_size + rctd * 12;
|
|
+ else
|
|
+ response_length = 2;
|
|
+ }
|
|
+
|
|
+ buf = kzalloc(response_length, GFP_KERNEL);
|
|
+ if (!buf) {
|
|
+ ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
+ goto out;
|
|
+ }
|
|
+ response_length = 0;
|
|
+
|
|
+ if (opts == 0) {
|
|
+ response_length += 4;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(tcm_supported_opcodes); i++) {
|
|
+ descr = tcm_supported_opcodes[i];
|
|
+ if (descr->enabled && !descr->enabled(cmd))
|
|
+ continue;
|
|
+
|
|
+ response_length += spc_rsoc_encode_command_descriptor(
|
|
+ &buf[response_length], rctd, descr);
|
|
+ }
|
|
+ put_unaligned_be32(response_length - 3, buf);
|
|
+ } else {
|
|
+ response_length = spc_rsoc_encode_one_command_descriptor(
|
|
+ &buf[response_length], rctd, descr,
|
|
+ cmd->se_dev);
|
|
+ }
|
|
+
|
|
+ memcpy(rbuf, buf, min_t(u32, response_length, cmd->data_length));
|
|
+out:
|
|
+ kfree(buf);
|
|
+ transport_kunmap_data_sg(cmd);
|
|
+
|
|
+ if (!ret)
|
|
+ target_complete_cmd_with_length(cmd, SAM_STAT_GOOD, response_length);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
sense_reason_t
|
|
spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
|
|
{
|
|
@@ -1439,6 +2355,10 @@ spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
|
|
cmd->execute_cmd =
|
|
target_emulate_report_target_port_groups;
|
|
}
|
|
+ if ((cdb[1] & 0x1f) ==
|
|
+ MI_REPORT_SUPPORTED_OPERATION_CODES)
|
|
+ cmd->execute_cmd =
|
|
+ spc_emulate_report_supp_op_codes;
|
|
*size = get_unaligned_be32(&cdb[6]);
|
|
} else {
|
|
/*
|
|
diff --git a/drivers/tty/serial/pxa_k1x.c b/drivers/tty/serial/pxa_k1x.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/tty/serial/pxa_k1x.c
|
|
+++ b/drivers/tty/serial/pxa_k1x.c
|
|
@@ -2075,7 +2075,7 @@ static int serial_pxa_probe_dt(struct platform_device *pdev, struct uart_pxa_por
|
|
|
|
#ifdef CONFIG_PM
|
|
if (of_property_read_u32(np, "edge-wakeup-pin", &sport->edge_wakeup_gpio)) {
|
|
- dev_info(&pdev->dev, "no edge-wakeup-pin defined\n");
|
|
+ dev_dbg(&pdev->dev, "no edge-wakeup-pin defined\n");
|
|
}
|
|
#endif
|
|
sport->device_ctrl_rts = of_property_read_bool(np, "device-control-rts");
|
|
@@ -2239,7 +2239,7 @@ static int serial_pxa_probe(struct platform_device *dev)
|
|
|
|
serial_pxa_ports[sport->port.line] = sport;
|
|
uart_add_one_port(&serial_pxa_reg, &sport->port);
|
|
- dev_info(&dev->dev, "uart clk_rate: %lu\n", clk_get_rate(sport->fclk));
|
|
+ dev_dbg(&dev->dev, "uart clk_rate: %lu\n", clk_get_rate(sport->fclk));
|
|
platform_set_drvdata(dev, sport);
|
|
|
|
#ifdef CONFIG_PM
|
|
diff --git a/drivers/usb/gadget/function/f_tcm.c b/drivers/usb/gadget/function/f_tcm.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/usb/gadget/function/f_tcm.c
|
|
+++ b/drivers/usb/gadget/function/f_tcm.c
|
|
@@ -249,6 +249,7 @@ static int bot_send_write_request(struct usbg_cmd *cmd)
|
|
int ret;
|
|
|
|
init_completion(&cmd->write_complete);
|
|
+ cmd->write_aborted = false;
|
|
cmd->fu = fu;
|
|
|
|
if (!cmd->data_len) {
|
|
@@ -264,11 +265,15 @@ static int bot_send_write_request(struct usbg_cmd *cmd)
|
|
if (ret)
|
|
goto cleanup;
|
|
ret = usb_ep_queue(fu->ep_out, fu->bot_req_out, GFP_KERNEL);
|
|
- if (ret)
|
|
- pr_err("%s(%d)\n", __func__, __LINE__);
|
|
+ if (ret) {
|
|
+ pr_err("%s(%d): %d\n", __func__, __LINE__, ret);
|
|
+ goto cleanup;
|
|
+ }
|
|
|
|
wait_for_completion(&cmd->write_complete);
|
|
- target_execute_cmd(se_cmd);
|
|
+ if (!cmd->write_aborted)
|
|
+ target_execute_cmd(se_cmd);
|
|
+
|
|
cleanup:
|
|
return ret;
|
|
}
|
|
@@ -833,6 +838,7 @@ static int uasp_send_write_request(struct usbg_cmd *cmd)
|
|
int ret;
|
|
|
|
init_completion(&cmd->write_complete);
|
|
+ cmd->write_aborted = false;
|
|
cmd->fu = fu;
|
|
|
|
iu->tag = cpu_to_be16(cmd->tag);
|
|
@@ -864,9 +870,13 @@ static int uasp_send_write_request(struct usbg_cmd *cmd)
|
|
pr_err("%s(%d)\n", __func__, __LINE__);
|
|
}
|
|
|
|
+ if (ret)
|
|
+ goto cleanup;
|
|
+
|
|
wait_for_completion(&cmd->write_complete);
|
|
|
|
- target_execute_cmd(se_cmd);
|
|
+ if (!cmd->write_aborted)
|
|
+ target_execute_cmd(se_cmd);
|
|
cleanup:
|
|
return ret;
|
|
}
|
|
@@ -1105,7 +1115,7 @@ static void usbg_data_write_cmpl(struct usb_ep *ep, struct usb_request *req)
|
|
stream->cmd = NULL;
|
|
target_put_sess_cmd(se_cmd);
|
|
transport_generic_free_cmd(&cmd->se_cmd, 0);
|
|
- return;
|
|
+ goto abort_completion;
|
|
}
|
|
|
|
if (req->status) {
|
|
@@ -1129,10 +1139,14 @@ static void usbg_data_write_cmpl(struct usb_ep *ep, struct usb_request *req)
|
|
if (cmd->state == UASP_QUEUE_COMMAND &&
|
|
cmd->tmr_rsp == RC_OVERLAPPED_TAG) {
|
|
uasp_send_tm_response(cmd);
|
|
- return;
|
|
+ goto abort_completion;
|
|
}
|
|
transport_send_check_condition_and_sense(se_cmd,
|
|
TCM_CHECK_CONDITION_ABORT_CMD, 0);
|
|
+abort_completion:
|
|
+ cmd->write_aborted = true;
|
|
+ complete(&cmd->write_complete);
|
|
+ return;
|
|
}
|
|
|
|
static int usbg_prepare_w_request(struct usbg_cmd *cmd, struct usb_request *req)
|
|
diff --git a/drivers/usb/gadget/function/tcm.h b/drivers/usb/gadget/function/tcm.h
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/usb/gadget/function/tcm.h
|
|
+++ b/drivers/usb/gadget/function/tcm.h
|
|
@@ -75,6 +75,7 @@ struct usbg_cmd {
|
|
struct se_cmd se_cmd;
|
|
void *data_buf; /* used if no sg support available */
|
|
struct f_uas *fu;
|
|
+ bool write_aborted;
|
|
struct completion write_complete;
|
|
struct kref ref;
|
|
|
|
diff --git a/include/linux/mfd/spacemit/spacemit_pmic.h b/include/linux/mfd/spacemit/spacemit_pmic.h
|
|
index 111111111111..222222222222 100644
|
|
--- a/include/linux/mfd/spacemit/spacemit_pmic.h
|
|
+++ b/include/linux/mfd/spacemit/spacemit_pmic.h
|
|
@@ -197,6 +197,7 @@ struct mfd_match_data {
|
|
/* regulator: match data */
|
|
struct regulator_match_data {
|
|
int nr_desc;
|
|
+ int sleep_reg_offset;
|
|
const struct regulator_desc *desc;
|
|
const char *name;
|
|
};
|
|
diff --git a/include/linux/mfd/spacemit/spm8821.h b/include/linux/mfd/spacemit/spm8821.h
|
|
index 111111111111..222222222222 100644
|
|
--- a/include/linux/mfd/spacemit/spm8821.h
|
|
+++ b/include/linux/mfd/spacemit/spm8821.h
|
|
@@ -83,6 +83,8 @@ enum SPM8821_reg {
|
|
#define SPM8821_NON_RESET_REG 0xAB
|
|
#define SPM8821_RESTART_CFG_BIT_MSK 0x3
|
|
|
|
+#define SPM8821_SLEEP_REG_OFFSET 0x1
|
|
+
|
|
#define SPM8821_REGMAP_CONFIG \
|
|
static const struct regmap_config spm8821_regmap_config = { \
|
|
.reg_bits = 8, \
|
|
@@ -104,7 +106,7 @@ enum SPM8821_reg {
|
|
#define SPM8821_BUCK_LINER_RANGE \
|
|
static const struct linear_range spm8821_buck_ranges[] = { \
|
|
REGULATOR_LINEAR_RANGE(500000, 0x0, 0xaa, 5000), \
|
|
- REGULATOR_LINEAR_RANGE(1375000, 0xab, 0xfe, 25000), \
|
|
+ REGULATOR_LINEAR_RANGE(1375000, 0xab, 0xff, 25000), \
|
|
};
|
|
|
|
|
|
@@ -790,6 +792,7 @@ static struct regulator_match_data spm8821_regulator_match_data = { \
|
|
.nr_desc = ARRAY_SIZE(spm8821_reg), \
|
|
.desc = spm8821_reg, \
|
|
.name = "spm8821", \
|
|
+ .sleep_reg_offset = SPM8821_SLEEP_REG_OFFSET, \
|
|
};
|
|
|
|
#endif /* __SPM8821_H__ */
|
|
diff --git a/include/scsi/scsi_proto.h b/include/scsi/scsi_proto.h
|
|
index 111111111111..222222222222 100644
|
|
--- a/include/scsi/scsi_proto.h
|
|
+++ b/include/scsi/scsi_proto.h
|
|
@@ -342,4 +342,14 @@ enum scsi_version_descriptor {
|
|
SCSI_VERSION_DESCRIPTOR_SRP = 0x0940
|
|
};
|
|
|
|
+enum scsi_support_opcode {
|
|
+ SCSI_SUPPORT_NO_INFO = 0,
|
|
+ SCSI_SUPPORT_NOT_SUPPORTED = 1,
|
|
+ SCSI_SUPPORT_FULL = 3,
|
|
+ SCSI_SUPPORT_VENDOR = 5,
|
|
+};
|
|
+
|
|
+#define SCSI_CONTROL_MASK 0
|
|
+#define SCSI_GROUP_NUMBER_MASK 0
|
|
+
|
|
#endif /* _SCSI_PROTO_H_ */
|
|
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
|
|
index 111111111111..222222222222 100644
|
|
--- a/include/target/target_core_base.h
|
|
+++ b/include/target/target_core_base.h
|
|
@@ -91,6 +91,8 @@
|
|
#define DA_EMULATE_ALUA 0
|
|
/* Emulate SCSI2 RESERVE/RELEASE and Persistent Reservations by default */
|
|
#define DA_EMULATE_PR 1
|
|
+/* Emulation for REPORT SUPPORTED OPERATION CODES */
|
|
+#define DA_EMULATE_RSOC 1
|
|
/* Enforce SCSI Initiator Port TransportID with 'ISID' for PR */
|
|
#define DA_ENFORCE_PR_ISIDS 1
|
|
/* Force SPC-3 PR Activate Persistence across Target Power Loss */
|
|
@@ -700,6 +702,7 @@ struct se_dev_attrib {
|
|
bool emulate_caw;
|
|
bool emulate_3pc;
|
|
bool emulate_pr;
|
|
+ bool emulate_rsoc;
|
|
enum target_prot_type pi_prot_type;
|
|
enum target_prot_type hw_pi_prot_type;
|
|
bool pi_prot_verify;
|
|
@@ -878,6 +881,21 @@ struct se_device {
|
|
struct mutex lun_reset_mutex;
|
|
};
|
|
|
|
+struct target_opcode_descriptor {
|
|
+ u8 support:3;
|
|
+ u8 serv_action_valid:1;
|
|
+ u8 opcode;
|
|
+ u16 service_action;
|
|
+ u32 cdb_size;
|
|
+ u8 specific_timeout;
|
|
+ u16 nominal_timeout;
|
|
+ u16 recommended_timeout;
|
|
+ bool (*enabled)(struct se_cmd *cmd);
|
|
+ void (*update_usage_bits)(u8 *usage_bits,
|
|
+ struct se_device *dev);
|
|
+ u8 usage_bits[];
|
|
+};
|
|
+
|
|
struct se_hba {
|
|
u16 hba_tpgt;
|
|
u32 hba_id;
|
|
diff --git a/init/version-timestamp.c b/init/version-timestamp.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/init/version-timestamp.c
|
|
+++ b/init/version-timestamp.c
|
|
@@ -27,5 +27,5 @@ struct uts_namespace init_uts_ns = {
|
|
|
|
/* FIXED STRINGS! Don't touch! */
|
|
const char linux_banner[] =
|
|
- "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
|
|
+ "Linux version " UTS_RELEASE " (" LINUX_VERSION_COMMITID ") (" LINUX_COMPILE_BY "@"
|
|
LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";
|
|
diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/sound/soc/codecs/es8316.c
|
|
+++ b/sound/soc/codecs/es8316.c
|
|
@@ -23,6 +23,13 @@
|
|
#include <sound/jack.h>
|
|
#include "es8316.h"
|
|
|
|
+#ifdef CONFIG_SOC_SPACEMIT_K1X
|
|
+/* 12.288MHz MCLK, 48kHz LRCK */
|
|
+#define NR_SUPPORTED_MCLK_LRCK_RATIOS 4
|
|
+static const unsigned int supported_mclk_lrck_ratios[] = {
|
|
+ 256, 384, 512, 768
|
|
+};
|
|
+#else
|
|
/* In slave mode at single speed, the codec is documented as accepting 5
|
|
* MCLK/LRCK ratios, but we also add ratio 400, which is commonly used on
|
|
* Intel Cherry Trail platforms (19.2MHz MCLK, 48kHz LRCK).
|
|
@@ -31,6 +38,7 @@
|
|
static const unsigned int supported_mclk_lrck_ratios[] = {
|
|
256, 384, 400, 512, 768, 1024
|
|
};
|
|
+#endif
|
|
|
|
struct es8316_priv {
|
|
struct mutex lock;
|
|
@@ -375,6 +383,7 @@ static int es8316_set_dai_sysclk(struct snd_soc_dai *codec_dai,
|
|
if (freq == 0)
|
|
return 0;
|
|
|
|
+ dev_dbg(component->dev, "set sysclk freq: %d\n", freq);
|
|
ret = clk_set_rate(es8316->mclk, freq);
|
|
if (ret)
|
|
return ret;
|
|
@@ -471,9 +480,12 @@ static int es8316_pcm_hw_params(struct snd_pcm_substream *substream,
|
|
u16 lrck_divider;
|
|
int i;
|
|
|
|
+ dev_dbg(component->dev, "set rate: %d\n", params_rate(params));
|
|
+
|
|
/* Validate supported sample rates that are autodetected from MCLK */
|
|
for (i = 0; i < NR_SUPPORTED_MCLK_LRCK_RATIOS; i++) {
|
|
const unsigned int ratio = supported_mclk_lrck_ratios[i];
|
|
+ dev_dbg(component->dev, "ratio %d, es8316->sysclk: %d\n", ratio, es8316->sysclk);
|
|
|
|
if (es8316->sysclk % ratio != 0)
|
|
continue;
|
|
@@ -505,6 +517,8 @@ static int es8316_pcm_hw_params(struct snd_pcm_substream *substream,
|
|
return -EINVAL;
|
|
}
|
|
|
|
+ dev_dbg(component->dev, "wordlen: %d, bclk_divider: %d\n", wordlen, bclk_divider);
|
|
+
|
|
snd_soc_component_update_bits(component, ES8316_SERDATA_DAC,
|
|
ES8316_SERDATA2_LEN_MASK, wordlen);
|
|
snd_soc_component_update_bits(component, ES8316_SERDATA_ADC,
|
|
@@ -762,6 +776,20 @@ static int es8316_probe(struct snd_soc_component *component)
|
|
*/
|
|
snd_soc_component_write(component, ES8316_CLKMGR_ADCOSR, 0x32);
|
|
|
|
+#ifdef CONFIG_SOC_SPACEMIT_K1X
|
|
+ /*DAC*/
|
|
+ snd_soc_component_write(component, ES8316_CPHP_ICAL_VOL, 0x00);
|
|
+ snd_soc_component_write(component, ES8316_HPMIX_VOL, 0xBB);
|
|
+ snd_soc_component_write(component, ES8316_DAC_VOLL, 0x11);
|
|
+ snd_soc_component_write(component, ES8316_DAC_VOLR, 0x01);
|
|
+ snd_soc_component_write(component, ES8316_HPMIX_SWITCH, 0x88);
|
|
+
|
|
+ /*ADC*/
|
|
+ snd_soc_component_write(component, ES8316_ADC_PGAGAIN, 0x70);
|
|
+ snd_soc_component_write(component, ES8316_ADC_VOLUME, 0x2A);
|
|
+ snd_soc_component_write(component, ES8316_ADC_PDN_LINSEL, 0x10);
|
|
+#endif
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/sound/soc/codecs/es8326.c b/sound/soc/codecs/es8326.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/sound/soc/codecs/es8326.c
|
|
+++ b/sound/soc/codecs/es8326.c
|
|
@@ -47,6 +47,11 @@ struct es8326_priv {
|
|
int jack_remove_retry;
|
|
#ifdef SPACEMIT_CONFIG_CODEC_ES8326
|
|
int spk_ctl_gpio;
|
|
+ int hp_gpio;
|
|
+ int hp_irq;
|
|
+ int mic_gpio;
|
|
+ int mic_irq;
|
|
+ struct delayed_work hpmic_detect_work;
|
|
#endif
|
|
};
|
|
|
|
@@ -465,9 +470,7 @@ static int es8326_pcm_hw_params(struct snd_pcm_substream *substream,
|
|
coeff_div = coeff_div_v3;
|
|
array = ARRAY_SIZE(coeff_div_v3);
|
|
}
|
|
-#ifdef SPACEMIT_CONFIG_CODEC_ES8326
|
|
- es8326->sysclk = params_rate(params) * 64;
|
|
-#endif
|
|
+
|
|
coeff = get_coeff(es8326->sysclk, params_rate(params), array, coeff_div);
|
|
/* bit size */
|
|
switch (params_format(params)) {
|
|
@@ -878,6 +881,72 @@ static irqreturn_t es8326_irq(int irq, void *dev_id)
|
|
return IRQ_HANDLED;
|
|
}
|
|
|
|
+#ifdef SPACEMIT_CONFIG_CODEC_ES8326
|
|
+static void es8326_hpmic_detect_handler(struct work_struct *work)
|
|
+{
|
|
+ struct es8326_priv *es8326 =
|
|
+ container_of(work, struct es8326_priv, hpmic_detect_work.work);
|
|
+ struct snd_soc_component *comp = es8326->component;
|
|
+ bool hp_status = 0, mic_status = 0;
|
|
+ u8 jack_status;
|
|
+
|
|
+ if (es8326->hp_gpio >= 0) {
|
|
+ hp_status = !gpio_get_value(es8326->hp_gpio);
|
|
+ }
|
|
+ if (es8326->mic_gpio >= 0) {
|
|
+ mic_status = !gpio_get_value(es8326->mic_gpio);
|
|
+ }
|
|
+ jack_status = hp_status | (mic_status << 1);
|
|
+ dev_dbg(comp->dev, "jack_status:%d\n", jack_status);
|
|
+ if ((jack_status & SND_JACK_HEADSET) == 0) {
|
|
+ /* Jack unplugged or spurious IRQ */
|
|
+ es8326_disable_micbias(es8326->component);
|
|
+ es8326->hp = 0;
|
|
+ regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x01);
|
|
+ regmap_write(es8326->regmap, ES8326_SYS_BIAS, 0x0a);
|
|
+ regmap_update_bits(es8326->regmap, ES8326_HP_DRIVER_REF, 0x0f, 0x03);
|
|
+
|
|
+ } else {
|
|
+ if (es8326->hp == 0) {
|
|
+ regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x01);
|
|
+ es8326_enable_micbias(es8326->component);
|
|
+ usleep_range(50000, 70000);
|
|
+ regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x00);
|
|
+ regmap_write(es8326->regmap, ES8326_SYS_BIAS, 0x1f);
|
|
+ regmap_update_bits(es8326->regmap, ES8326_HP_DRIVER_REF, 0x0f, 0x08);
|
|
+ usleep_range(10000, 15000);
|
|
+ es8326->hp = 1;
|
|
+ regmap_write(es8326->regmap, ES8326_ADC_SCALE, 0x33);
|
|
+ regmap_update_bits(es8326->regmap, ES8326_PGA_PDN,
|
|
+ 0x08, 0x08);
|
|
+ regmap_update_bits(es8326->regmap, ES8326_PGAGAIN,
|
|
+ 0x80, 0x80);
|
|
+ regmap_write(es8326->regmap, ES8326_ADC1_SRC, 0x00);
|
|
+ regmap_write(es8326->regmap, ES8326_ADC2_SRC, 0x00);
|
|
+ regmap_update_bits(es8326->regmap, ES8326_PGA_PDN,
|
|
+ 0x08, 0x00);
|
|
+ usleep_range(10000, 15000);
|
|
+ }
|
|
+ }
|
|
+ snd_soc_jack_report(es8326->jack,
|
|
+ jack_status,
|
|
+ SND_JACK_HEADSET);
|
|
+ return;
|
|
+}
|
|
+
|
|
+static irqreturn_t es8326_irq_hpmic(int irq, void *dev_id)
|
|
+{
|
|
+ struct es8326_priv *es8326 = dev_id;
|
|
+
|
|
+ if (!es8326->jack)
|
|
+ goto out;
|
|
+ queue_delayed_work(system_wq, &es8326->hpmic_detect_work,
|
|
+ msecs_to_jiffies(100));
|
|
+out:
|
|
+ return IRQ_HANDLED;
|
|
+}
|
|
+#endif
|
|
+
|
|
static int es8326_calibrate(struct snd_soc_component *component)
|
|
{
|
|
struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component);
|
|
@@ -1209,7 +1278,14 @@ static void es8326_enable_jack_detect(struct snd_soc_component *component,
|
|
es8326->jack = jack;
|
|
|
|
mutex_unlock(&es8326->lock);
|
|
+#ifdef SPACEMIT_CONFIG_CODEC_ES8326
|
|
+ if (es8326->irq > 0)
|
|
+ es8326_irq(es8326->irq, es8326);
|
|
+ else
|
|
+ es8326_irq_hpmic(es8326->irq, es8326);
|
|
+#else
|
|
es8326_irq(es8326->irq, es8326);
|
|
+#endif
|
|
}
|
|
|
|
static void es8326_disable_jack_detect(struct snd_soc_component *component)
|
|
@@ -1292,6 +1368,10 @@ static int es8326_i2c_probe(struct i2c_client *i2c,
|
|
es8326_jack_detect_handler);
|
|
INIT_DELAYED_WORK(&es8326->button_press_work,
|
|
es8326_jack_button_handler);
|
|
+#ifdef SPACEMIT_CONFIG_CODEC_ES8326
|
|
+ INIT_DELAYED_WORK(&es8326->hpmic_detect_work,
|
|
+ es8326_hpmic_detect_handler);
|
|
+#endif
|
|
/* ES8316 is level-based while ES8326 is edge-based */
|
|
ret = devm_request_threaded_irq(&i2c->dev, es8326->irq, NULL, es8326_irq,
|
|
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
|
|
@@ -1319,6 +1399,36 @@ static int es8326_i2c_probe(struct i2c_client *i2c,
|
|
}
|
|
es8326_enable_spk(es8326, false);
|
|
}
|
|
+ es8326->hp_gpio = of_get_named_gpio_flags(i2c->dev.of_node,
|
|
+ "hp-detect-gpio", 0, &flags);
|
|
+ if (es8326->hp_gpio < 0) {
|
|
+ dev_info(&i2c->dev, "Can not read property hp-detect-gpio\n");
|
|
+ es8326->hp_gpio = -1;
|
|
+ } else {
|
|
+ es8326->hp_irq = gpio_to_irq(es8326->hp_gpio);
|
|
+ ret = request_irq(es8326->hp_irq, es8326_irq_hpmic,
|
|
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
|
+ "es8326-hp-irq", es8326);
|
|
+ if (ret) {
|
|
+ dev_err(&i2c->dev, "Failed to request hp-irq\n");
|
|
+ return ret;
|
|
+ }
|
|
+ }
|
|
+ es8326->mic_gpio = of_get_named_gpio_flags(i2c->dev.of_node,
|
|
+ "mic-detect-gpio", 0, &flags);
|
|
+ if (es8326->mic_gpio < 0) {
|
|
+ dev_info(&i2c->dev, "Can not read property mic-detect-gpio\n");
|
|
+ es8326->mic_gpio = -1;
|
|
+ } else {
|
|
+ es8326->mic_irq = gpio_to_irq(es8326->mic_gpio);
|
|
+ ret = request_irq(es8326->mic_irq, es8326_irq_hpmic,
|
|
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
|
+ "es8326-mic-irq", es8326);
|
|
+ if (ret) {
|
|
+ dev_err(&i2c->dev, "Failed to request mic-irq\n");
|
|
+ return ret;
|
|
+ }
|
|
+ }
|
|
#endif
|
|
es8326->mclk = devm_clk_get_optional(&i2c->dev, "mclk");
|
|
if (IS_ERR(es8326->mclk)) {
|
|
diff --git a/sound/soc/spacemit/spacemit-snd-card.c b/sound/soc/spacemit/spacemit-snd-card.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/sound/soc/spacemit/spacemit-snd-card.c
|
|
+++ b/sound/soc/spacemit/spacemit-snd-card.c
|
|
@@ -21,6 +21,54 @@
|
|
#define CELL "#sound-dai-cells"
|
|
#define PREFIX "simple-audio-card,"
|
|
|
|
+
|
|
+int spacemit_simple_hw_params(struct snd_pcm_substream *substream,
|
|
+ struct snd_pcm_hw_params *params)
|
|
+{
|
|
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
|
+ struct snd_soc_dai *sdai;
|
|
+ struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card);
|
|
+ struct simple_dai_props *props = simple_priv_to_props(priv, rtd->num);
|
|
+ unsigned int mclk, mclk_fs = 0;
|
|
+ int i, ret;
|
|
+
|
|
+ if (props->mclk_fs)
|
|
+ mclk_fs = props->mclk_fs;
|
|
+
|
|
+ if (mclk_fs) {
|
|
+ struct snd_soc_component *component;
|
|
+ mclk = params_rate(params) * mclk_fs;
|
|
+
|
|
+ /* Ensure sysclk is set on all components in case any
|
|
+ * (such as platform components) are missed by calls to
|
|
+ * snd_soc_dai_set_sysclk.
|
|
+ */
|
|
+ for_each_rtd_components(rtd, i, component) {
|
|
+ ret = snd_soc_component_set_sysclk(component, 0, 0,
|
|
+ mclk, SND_SOC_CLOCK_IN);
|
|
+ if (ret && ret != -ENOTSUPP)
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ for_each_rtd_codec_dais(rtd, i, sdai) {
|
|
+ ret = snd_soc_dai_set_sysclk(sdai, 0, mclk, SND_SOC_CLOCK_IN);
|
|
+ if (ret && ret != -ENOTSUPP)
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ for_each_rtd_cpu_dais(rtd, i, sdai) {
|
|
+ ret = snd_soc_dai_set_sysclk(sdai, 0, mclk, SND_SOC_CLOCK_OUT);
|
|
+ if (ret && ret != -ENOTSUPP)
|
|
+ return ret;
|
|
+ }
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static const struct snd_soc_ops simple_ops = {
|
|
+ .hw_params = spacemit_simple_hw_params,
|
|
+};
|
|
+
|
|
static int asoc_simple_parse_dai(struct device_node *node,
|
|
struct snd_soc_dai_link_component *dlc,
|
|
int *is_single_link)
|
|
@@ -161,6 +209,7 @@ static int asoc_simple_card_dai_link_of(struct device_node *node,
|
|
char prop[128];
|
|
char *prefix = "";
|
|
int ret, single_cpu;
|
|
+ unsigned int val = 0;
|
|
|
|
if (is_top_level_node)
|
|
prefix = PREFIX;
|
|
@@ -220,6 +269,12 @@ static int asoc_simple_card_dai_link_of(struct device_node *node,
|
|
dai_link->init = asoc_simple_card_jack_init;
|
|
}
|
|
|
|
+ dai_link->ops = &simple_ops;
|
|
+ if (!of_property_read_u32(node, "spacemit,mclk-fs", &val)) {
|
|
+ priv->dai_props->mclk_fs = val;
|
|
+ } else {
|
|
+ priv->dai_props->mclk_fs = 256;
|
|
+ }
|
|
asoc_simple_canonicalize_cpu(dai_link->cpus, single_cpu);
|
|
asoc_simple_canonicalize_platform(dai_link->platforms, dai_link->cpus);
|
|
|
|
diff --git a/sound/soc/spacemit/spacemit-snd-i2s.c b/sound/soc/spacemit/spacemit-snd-i2s.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/sound/soc/spacemit/spacemit-snd-i2s.c
|
|
+++ b/sound/soc/spacemit/spacemit-snd-i2s.c
|
|
@@ -85,6 +85,7 @@ struct sspa_priv {
|
|
int dai_id_pre;
|
|
int running_cnt;
|
|
struct platform_device *i2splatdev;
|
|
+ unsigned int sysclk;
|
|
};
|
|
|
|
static void i2s_sspa_write_reg(struct ssp_device *sspa, u32 reg, u32 val)
|
|
@@ -117,6 +118,15 @@ static void i2s_sspa_shutdown(struct snd_pcm_substream *substream,
|
|
static int i2s_sspa_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
|
|
int clk_id, unsigned int freq, int dir)
|
|
{
|
|
+ struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(cpu_dai);
|
|
+
|
|
+ if (sspa_priv->running_cnt)
|
|
+ return 0;
|
|
+
|
|
+ if (sspa_priv->sysclk == freq)
|
|
+ return 0;
|
|
+
|
|
+ sspa_priv->sysclk = freq;
|
|
return 0;
|
|
}
|
|
|
|
@@ -207,13 +217,35 @@ static int i2s_sspa_hw_params(struct snd_pcm_substream *substream,
|
|
struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(dai);
|
|
struct ssp_device *sspa = sspa_priv->sspa;
|
|
struct snd_dmaengine_dai_dma_data *dma_params;
|
|
+ unsigned int mclk_fs, val, target;
|
|
|
|
- pr_debug("%s, format=0x%x\n", __FUNCTION__, params_format(params));
|
|
dma_params = &sspa_priv->dma_params[substream->stream];
|
|
dma_params->addr = (sspa->phys_base + DATAR);
|
|
dma_params->maxburst = 32;
|
|
dma_params->addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
|
|
snd_soc_dai_set_dma_data(cpu_dai, substream, dma_params);
|
|
+
|
|
+ if (sspa_priv->running_cnt)
|
|
+ return 0;
|
|
+
|
|
+ mclk_fs = sspa_priv->sysclk / (params_rate(params));
|
|
+ switch (mclk_fs) {
|
|
+ case 64:
|
|
+ target = SYSCLK_BASE_156M | 0 << 27| 4 << 15 | 200; //64fs
|
|
+ break;
|
|
+ case 128:
|
|
+ target = SYSCLK_BASE_156M | 1 << 27| 8 << 15 | 200; //128fs
|
|
+ break;
|
|
+ case 256:
|
|
+ target = SYSCLK_BASE_156M | 3 << 27| 16 << 15 | 200; //256fs
|
|
+ break;
|
|
+ default:
|
|
+ target = SYSCLK_BASE_156M | 3 << 27| 16 << 15 | 200; //256fs
|
|
+ break;
|
|
+ }
|
|
+ val = __raw_readl(sspa->pmumain + ISCCR1);
|
|
+ val = val & ~0x5FFFFFFF;
|
|
+ __raw_writel(val | target, sspa->pmumain + ISCCR1);
|
|
return 0;
|
|
}
|
|
|
|
@@ -274,9 +306,6 @@ static int i2s_sspa_probe(struct snd_soc_dai *dai)
|
|
struct sspa_priv *priv = dev_get_drvdata(dai->dev);
|
|
struct ssp_device *sspa = priv->sspa;
|
|
unsigned int sspa_clk = 0;
|
|
- pr_debug("%s\n", __FUNCTION__);
|
|
- //init clock
|
|
- __raw_writel((SYSCLK_BASE_156M | BITCLK_DIV_468| FRAME_48K_I2S | 200), sspa->pmumain + ISCCR1);
|
|
|
|
if (dai->id == 0)
|
|
{
|
|
@@ -372,7 +401,7 @@ static int asoc_i2s_sspa_probe(struct platform_device *pdev)
|
|
struct resource *res;
|
|
u8 dai_id = 0;
|
|
|
|
- printk("enter %s\n", __FUNCTION__);
|
|
+ pr_debug("enter %s\n", __FUNCTION__);
|
|
priv = devm_kzalloc(&pdev->dev,
|
|
sizeof(struct sspa_priv), GFP_KERNEL);
|
|
if (!priv) {
|
|
@@ -456,7 +485,7 @@ static struct platform_driver asoc_i2s_sspa_driver = {
|
|
#if IS_MODULE(CONFIG_SND_SOC_SPACEMIT)
|
|
int spacemit_snd_register_i2s_pdrv(void)
|
|
{
|
|
- printk("%s\n", __FUNCTION__);
|
|
+ pr_debug("%s\n", __FUNCTION__);
|
|
return platform_driver_register(&asoc_i2s_sspa_driver);
|
|
}
|
|
|
|
diff --git a/sound/soc/spacemit/spacemit-snd-pcm-dma.c b/sound/soc/spacemit/spacemit-snd-pcm-dma.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/sound/soc/spacemit/spacemit-snd-pcm-dma.c
|
|
+++ b/sound/soc/spacemit/spacemit-snd-pcm-dma.c
|
|
@@ -731,7 +731,7 @@ static int spacemit_snd_pcm_new(struct snd_soc_component *component, struct snd_
|
|
struct snd_card *card = rtd->card->snd_card;
|
|
struct snd_pcm *pcm = rtd->pcm;
|
|
|
|
- printk("%s enter, dev=%s\n", __FUNCTION__, dev_name(rtd->dev));
|
|
+ pr_debug("%s enter, dev=%s\n", __FUNCTION__, dev_name(rtd->dev));
|
|
|
|
if (!component) {
|
|
pr_err("%s: coundn't find component %s\n", __FUNCTION__, DRV_NAME);
|
|
@@ -745,7 +745,7 @@ static int spacemit_snd_pcm_new(struct snd_soc_component *component, struct snd_
|
|
}
|
|
if (dev->dmadata->dma_id == DMA_HDMI) {
|
|
chan_num = 1;
|
|
- printk("%s playback_only, dev=%s\n", __FUNCTION__, dev_name(rtd->dev));
|
|
+ pr_debug("%s playback_only, dev=%s\n", __FUNCTION__, dev_name(rtd->dev));
|
|
}else{
|
|
chan_num = 2;
|
|
}
|
|
@@ -810,7 +810,7 @@ static void spacemit_snd_pcm_remove(struct snd_soc_component *component)
|
|
int chan_num;
|
|
struct spacemit_snd_soc_device *dev = snd_soc_component_get_drvdata(component);
|
|
|
|
- pr_info("%s enter\n", __FUNCTION__);
|
|
+ pr_debug("%s enter\n", __FUNCTION__);
|
|
|
|
if (dev->dmadata->dma_id == DMA_HDMI) {
|
|
chan_num = 1;
|
|
@@ -969,12 +969,12 @@ static int spacemit_snd_dma_pdev_probe(struct platform_device *pdev)
|
|
return -ENOMEM;
|
|
}
|
|
|
|
- printk("%s enter: dev name %s\n", __func__, dev_name(&pdev->dev));
|
|
+ pr_debug("%s enter: dev name %s\n", __func__, dev_name(&pdev->dev));
|
|
|
|
if (of_device_is_compatible(np, "spacemit,spacemit-snd-dma-hdmi")){
|
|
device->dmadata->dma_id = DMA_HDMI;
|
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
- printk("%s, start=0x%lx, end=0x%lx\n", __FUNCTION__, (unsigned long)res->start, (unsigned long)res->end);
|
|
+ pr_debug("%s, start=0x%lx, end=0x%lx\n", __FUNCTION__, (unsigned long)res->start, (unsigned long)res->end);
|
|
priv.phy_addr = res->start;
|
|
priv.buf_base = devm_ioremap_resource(&pdev->dev, res);
|
|
if (IS_ERR(priv.buf_base)) {
|
|
@@ -1026,7 +1026,7 @@ static struct platform_driver spacemit_snd_dma_pdrv = {
|
|
#if IS_MODULE(CONFIG_SND_SOC_SPACEMIT)
|
|
int spacemit_snd_register_dmaclient_pdrv(void)
|
|
{
|
|
- printk("%s enter\n", __FUNCTION__);
|
|
+ pr_debug("%s enter\n", __FUNCTION__);
|
|
return platform_driver_register(&spacemit_snd_dma_pdrv);
|
|
}
|
|
EXPORT_SYMBOL(spacemit_snd_register_dmaclient_pdrv);
|
|
diff --git a/sound/soc/spacemit/spacemit-snd-sspa.c b/sound/soc/spacemit/spacemit-snd-sspa.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/sound/soc/spacemit/spacemit-snd-sspa.c
|
|
+++ b/sound/soc/spacemit/spacemit-snd-sspa.c
|
|
@@ -100,7 +100,7 @@ static int mmp_sspa_hw_params(struct snd_pcm_substream *substream,
|
|
struct snd_dmaengine_dai_dma_data *dma_params;
|
|
|
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
|
- printk("%s, format=0x%x\n", __FUNCTION__, params_format(params));
|
|
+ pr_debug("%s, format=0x%x\n", __FUNCTION__, params_format(params));
|
|
dma_params = sspa_priv->dma_params;
|
|
dma_params->maxburst = 32;
|
|
dma_params->addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
|
|
--
|
|
Armbian
|
|
|