mirror of
https://github.com/Fishwaldo/build.git
synced 2025-07-10 06:59:02 +00:00
Odroid C2 NEXT and DEV branches, need testing
This commit is contained in:
parent
29da133ef7
commit
b779446b58
100 changed files with 34623 additions and 4 deletions
5614
config/kernel/linux-odroidc2-dev.config
Normal file
5614
config/kernel/linux-odroidc2-dev.config
Normal file
File diff suppressed because it is too large
Load diff
5598
config/kernel/linux-odroidc2-next.config
Normal file
5598
config/kernel/linux-odroidc2-next.config
Normal file
File diff suppressed because it is too large
Load diff
|
@ -11,13 +11,27 @@ HAS_UUID_SUPPORT=yes
|
|||
# NOTE: This u-boot version incorrectly parses boot.scr header
|
||||
# due to wrong data type for 64 bit compiler, so boot.scr doesn't work
|
||||
|
||||
KERNELSOURCE='https://github.com/hardkernel/linux'
|
||||
KERNELBRANCH='branch:odroidc2-3.14.y'
|
||||
KERNELDIR='linux-odroidc2'
|
||||
|
||||
ARCH=arm64
|
||||
KERNEL_IMAGE_TYPE=Image
|
||||
|
||||
case $BRANCH in
|
||||
default)
|
||||
KERNELSOURCE='https://github.com/hardkernel/linux'
|
||||
KERNELBRANCH='branch:odroidc2-3.14.y'
|
||||
KERNELDIR='linux-odroidc2'
|
||||
;;
|
||||
next)
|
||||
KERNELSOURCE=$MAINLINE_KERNEL_SOURCE
|
||||
KERNELBRANCH='branch:v4.10.17'
|
||||
KERNELDIR=$MAINLINE_KERNEL_DIR
|
||||
;;
|
||||
dev)
|
||||
KERNELSOURCE=$MAINLINE_KERNEL_SOURCE
|
||||
KERNELBRANCH='branch:master'
|
||||
KERNELDIR=$MAINLINE_KERNEL_DIR
|
||||
;;
|
||||
esac
|
||||
|
||||
CPUMIN=500000
|
||||
CPUMAX=1536000
|
||||
GOVERNOR=ondemand
|
||||
|
|
11
patch/kernel/odroidc2-dev/bash_to_afterinstall.patch
Normal file
11
patch/kernel/odroidc2-dev/bash_to_afterinstall.patch
Normal file
|
@ -0,0 +1,11 @@
|
|||
--- a/scripts/package/builddeb
|
||||
+++ b/scripts/package/builddeb
|
||||
@@ -218,7 +218,7 @@
|
||||
for script in postinst postrm preinst prerm ; do
|
||||
mkdir -p "$tmpdir$debhookdir/$script.d"
|
||||
cat <<EOF > "$tmpdir/DEBIAN/$script"
|
||||
-#!/bin/sh
|
||||
+#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
|
@ -0,0 +1,198 @@
|
|||
diff --git a/scripts/package/builddeb b/scripts/package/builddeb
|
||||
index 807c9cd..9b9435f 100755
|
||||
--- a/scripts/package/builddeb
|
||||
+++ b/scripts/package/builddeb
|
||||
@@ -29,6 +29,28 @@ create_package() {
|
||||
# in case we are in a restrictive umask environment like 0077
|
||||
chmod -R a+rX "$pdir"
|
||||
|
||||
+ # Create preinstall and post install script to remove dtb
|
||||
+ if [[ "$1" == *dtb* ]]; then
|
||||
+ echo "if [ -d /boot/dtb-$version ]; then mv /boot/dtb-$version /boot/dtb-$version.old; fi" >> $pdir/DEBIAN/preinst
|
||||
+ echo "if [ -d /boot/dtb.old ]; then rm -rf /boot/dtb.old; fi" >> $pdir/DEBIAN/preinst
|
||||
+ echo "if [ -d /dtb ]; then mv /dtb /dtb.old; fi" >> $pdir/DEBIAN/preinst
|
||||
+ echo "if [ -d /boot/dtb ]; then mv /boot/dtb /boot/dtb.old; fi" >> $pdir/DEBIAN/preinst
|
||||
+ echo "exit 0" >> $pdir/DEBIAN/preinst
|
||||
+ chmod 775 $pdir/DEBIAN/preinst
|
||||
+ #
|
||||
+ echo "if [ -d /boot/dtb-$version.old ]; then rm -rf /boot/dtb-$version.old; fi" >> $pdir/DEBIAN/postinst
|
||||
+ echo "ln -sf dtb-$version /boot/dtb > /dev/null 2>&1 || mv /boot/dtb-$version /boot/dtb" >> $pdir/DEBIAN/postinst
|
||||
+ echo "exit 0" >> $pdir/DEBIAN/postinst
|
||||
+ chmod 775 $pdir/DEBIAN/postinst
|
||||
+ fi
|
||||
+
|
||||
+ # Create postinstall script for headers
|
||||
+ if [[ "$1" == *headers* ]]; then
|
||||
+ echo "cd /usr/src/linux-headers-$version; echo \"Compiling headers - please wait ...\"; make -s scripts >/dev/null 2>&1" >> $pdir/DEBIAN/postinst
|
||||
+ echo "exit 0" >> $pdir/DEBIAN/postinst
|
||||
+ chmod 775 $pdir/DEBIAN/postinst
|
||||
+ fi
|
||||
+
|
||||
# Create the package
|
||||
dpkg-gencontrol $forcearch -Vkernel:debarch="${debarch}" -p$pname -P"$pdir"
|
||||
dpkg --build "$pdir" ..
|
||||
@@ -95,11 +117,13 @@ tmpdir="$objtree/debian/tmp"
|
||||
fwdir="$objtree/debian/fwtmp"
|
||||
kernel_headers_dir="$objtree/debian/hdrtmp"
|
||||
libc_headers_dir="$objtree/debian/headertmp"
|
||||
+dtb_dir="$objtree/debian/dtbtmp"
|
||||
dbg_dir="$objtree/debian/dbgtmp"
|
||||
-packagename=linux-image-$version
|
||||
-fwpackagename=linux-firmware-image-$version
|
||||
-kernel_headers_packagename=linux-headers-$version
|
||||
-libc_headers_packagename=linux-libc-dev
|
||||
+packagename=linux-image-dev"$LOCALVERSION"
|
||||
+fwpackagename=linux-firmware-image-dev"$LOCALVERSION"
|
||||
+kernel_headers_packagename=linux-headers-dev"$LOCALVERSION"
|
||||
+dtb_packagename=linux-dtb-dev"$LOCALVERSION"
|
||||
+libc_headers_packagename=linux-libc-dev-dev"$LOCALVERSION"
|
||||
dbg_packagename=$packagename-dbg
|
||||
debarch=
|
||||
forcearch=
|
||||
@@ -126,7 +150,9 @@ esac
|
||||
BUILD_DEBUG="$(grep -s '^CONFIG_DEBUG_INFO=y' $KCONFIG_CONFIG || true)"
|
||||
|
||||
# Setup the directory structure
|
||||
-rm -rf "$tmpdir" "$fwdir" "$kernel_headers_dir" "$libc_headers_dir" "$dbg_dir" $objtree/debian/files
|
||||
+rm -rf "$tmpdir" "$fwdir" "$kernel_headers_dir" "$libc_headers_dir" "$dbg_dir" "$dtb_dir" $objtree/debian/files
|
||||
+mkdir -m 755 -p "$dtb_dir/DEBIAN"
|
||||
+mkdir -p "$dtb_dir/boot/dtb-$version" "$dtb_dir/usr/share/doc/$dtb_packagename"
|
||||
mkdir -m 755 -p "$tmpdir/DEBIAN"
|
||||
mkdir -p "$tmpdir/lib" "$tmpdir/boot"
|
||||
mkdir -p "$fwdir/lib/firmware/$version/"
|
||||
@@ -180,6 +206,11 @@ if grep -q '^CONFIG_MODULES=y' $KCONFIG_CONFIG ; then
|
||||
fi
|
||||
fi
|
||||
|
||||
+if grep -q '^CONFIG_OF=y' $KCONFIG_CONFIG ; then
|
||||
+ #mkdir -p "$tmpdir/boot/dtb"
|
||||
+ INSTALL_DTBS_PATH="$dtb_dir/boot/dtb-$version" $MAKE KBUILD_SRC= dtbs_install
|
||||
+fi
|
||||
+
|
||||
if [ "$ARCH" != "um" ]; then
|
||||
$MAKE headers_check KBUILD_SRC=
|
||||
$MAKE headers_install KBUILD_SRC= INSTALL_HDR_PATH="$libc_headers_dir/usr"
|
||||
@@ -192,7 +223,7 @@ fi
|
||||
# so do we; recent versions of dracut and initramfs-tools will obey this.
|
||||
debhookdir=${KDEB_HOOKDIR:-/etc/kernel}
|
||||
if grep -q '^CONFIG_BLK_DEV_INITRD=y' $KCONFIG_CONFIG; then
|
||||
- want_initrd=Yes
|
||||
+ want_initrd=Yes
|
||||
else
|
||||
want_initrd=No
|
||||
fi
|
||||
@@ -204,9 +235,11 @@ for script in postinst postrm preinst prerm ; do
|
||||
set -e
|
||||
|
||||
# Pass maintainer script parameters to hook scripts
|
||||
+
|
||||
export DEB_MAINT_PARAMS="\$*"
|
||||
|
||||
# Tell initramfs builder whether it's wanted
|
||||
+
|
||||
export INITRD=$want_initrd
|
||||
|
||||
test -d $debhookdir/$script.d && run-parts --arg="$version" --arg="/$installed_image_path" $debhookdir/$script.d
|
||||
@@ -215,6 +248,55 @@ EOF
|
||||
chmod 755 "$tmpdir/DEBIAN/$script"
|
||||
done
|
||||
|
||||
+##
|
||||
+## Create sym link to kernel image
|
||||
+##
|
||||
+sed -e "s/set -e//g" -i $tmpdir/DEBIAN/postinst
|
||||
+sed -e "s/exit 0//g" -i $tmpdir/DEBIAN/postinst
|
||||
+cat >> $tmpdir/DEBIAN/postinst <<EOT
|
||||
+if [ "\$(grep nand /proc/partitions)" != "" ] && [ "\$(grep mmc /proc/partitions)" = "" ]; then
|
||||
+mkimage -A arm -O linux -T kernel -C none -a "0x40008000" -e "0x40008000" -n "Linux kernel" -d /$installed_image_path /boot/uImage > /dev/null 2>&1
|
||||
+cp /boot/uImage /tmp/uImage
|
||||
+sync
|
||||
+mountpoint -q /boot || mount /boot
|
||||
+cp /tmp/uImage /boot/uImage
|
||||
+rm -f /$installed_image_path
|
||||
+else
|
||||
+ln -sf $(basename $installed_image_path) /boot/zImage > /dev/null 2>&1 || mv /$installed_image_path /boot/zImage
|
||||
+fi
|
||||
+touch /boot/.next
|
||||
+exit 0
|
||||
+EOT
|
||||
+##
|
||||
+## FAT install workaround
|
||||
+##
|
||||
+sed -e "s/set -e//g" -i $tmpdir/DEBIAN/preinst
|
||||
+sed -e "s/exit 0//g" -i $tmpdir/DEBIAN/preinst
|
||||
+cat >> $tmpdir/DEBIAN/preinst <<EOT
|
||||
+# exit if we are running chroot
|
||||
+if [ "\$(stat -c %d:%i /)" != "\$(stat -c %d:%i /proc/1/root/.)" ]; then exit 0; fi
|
||||
+
|
||||
+check_and_unmount (){
|
||||
+boot_device=\$(mountpoint -d /boot)
|
||||
+
|
||||
+for file in /dev/* ; do
|
||||
+ CURRENT_DEVICE=\$(printf "%d:%d" \$(stat --printf="0x%t 0x%T" \$file))
|
||||
+ if [[ "\$CURRENT_DEVICE" = "\$boot_device" ]]; then
|
||||
+ boot_partition=\$file
|
||||
+ break;
|
||||
+ fi
|
||||
+done
|
||||
+
|
||||
+bootfstype=\$(blkid -s TYPE -o value \$boot_partition)
|
||||
+if [ "\$bootfstype" = "vfat" ]; then
|
||||
+umount /boot;
|
||||
+rm -f /boot/System.map* /boot/config* /boot/vmlinuz* /boot/zImage /boot/uImage
|
||||
+fi
|
||||
+}
|
||||
+mountpoint -q /boot && check_and_unmount
|
||||
+EOT
|
||||
+echo "exit 0" >> $tmpdir/DEBIAN/preinst
|
||||
+
|
||||
# Try to determine maintainer and email values
|
||||
if [ -n "$DEBEMAIL" ]; then
|
||||
email=$DEBEMAIL
|
||||
@@ -329,12 +411,20 @@ if grep -q '^CONFIG_GCC_PLUGINS=y' $KCONFIG_CONFIG ; then
|
||||
fi
|
||||
destdir=$kernel_headers_dir/usr/src/linux-headers-$version
|
||||
mkdir -p "$destdir"
|
||||
+######################## headers patch
|
||||
+ZACNI=$(pwd)
|
||||
+cd $destdir
|
||||
+patch -p1 < /tmp/headers-debian-byteshift.patch
|
||||
+cd $ZACNI
|
||||
+######################## headers patch
|
||||
(cd $srctree; tar -c -f - -T -) < "$objtree/debian/hdrsrcfiles" | (cd $destdir; tar -xf -)
|
||||
(cd $objtree; tar -c -f - -T -) < "$objtree/debian/hdrobjfiles" | (cd $destdir; tar -xf -)
|
||||
(cd $objtree; cp $KCONFIG_CONFIG $destdir/.config) # copy .config manually to be where it's expected to be
|
||||
ln -sf "/usr/src/linux-headers-$version" "$kernel_headers_dir/lib/modules/$version/build"
|
||||
rm -f "$objtree/debian/hdrsrcfiles" "$objtree/debian/hdrobjfiles"
|
||||
|
||||
+(cd "$destdir"; make M=scripts clean)
|
||||
+
|
||||
cat <<EOF >> debian/control
|
||||
|
||||
Package: $kernel_headers_packagename
|
||||
@@ -363,6 +453,16 @@ fi
|
||||
|
||||
cat <<EOF >> debian/control
|
||||
|
||||
+Package: $dtb_packagename
|
||||
+Architecture: any
|
||||
+Description: Linux DTB, version $version
|
||||
+ This package contains device blobs from the Linux kernel, version $version.
|
||||
+EOF
|
||||
+
|
||||
+create_package "$dtb_packagename" "$dtb_dir"
|
||||
+
|
||||
+cat <<EOF >> debian/control
|
||||
+
|
||||
Package: $libc_headers_packagename
|
||||
Section: devel
|
||||
Provides: linux-kernel-headers
|
||||
@@ -374,7 +474,7 @@ EOF
|
||||
|
||||
if [ "$ARCH" != "um" ]; then
|
||||
create_package "$kernel_headers_packagename" "$kernel_headers_dir"
|
||||
- create_package "$libc_headers_packagename" "$libc_headers_dir"
|
||||
+# create_package "$libc_headers_packagename" "$libc_headers_dir"
|
||||
fi
|
||||
|
||||
create_package "$packagename" "$tmpdir"
|
|
@ -0,0 +1,32 @@
|
|||
From 86f0b91719a9d97095187af6ddaade3b34dc1257 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Thu, 16 Mar 2017 09:38:10 +0100
|
||||
Subject: [PATCH 01/93] ARM64: dts: meson-gxbb: Add gpio-ranges
|
||||
|
||||
---
|
||||
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
index b353073..2be29a3 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
@@ -186,6 +186,7 @@
|
||||
reg-names = "mux", "pull", "gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
+ gpio-ranges = <&pinctrl_aobus 0 0 14>;
|
||||
};
|
||||
|
||||
uart_ao_a_pins: uart_ao_a {
|
||||
@@ -279,6 +280,7 @@
|
||||
reg-names = "mux", "pull", "pull-enable", "gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
+ gpio-ranges = <&pinctrl_periphs 0 14 120>;
|
||||
};
|
||||
|
||||
emmc_pins: emmc {
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
From be24356f2a4214a9efbb28441f58cfd91aefb4b4 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Thu, 16 Mar 2017 09:40:16 +0100
|
||||
Subject: [PATCH 02/93] pinctrl: meson: use gpio-ranges from DT
|
||||
|
||||
---
|
||||
drivers/pinctrl/meson/pinctrl-meson.c | 14 +-------------
|
||||
1 file changed, 1 insertion(+), 13 deletions(-)
|
||||
|
||||
diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c
|
||||
index 620c231a..3372ce9 100644
|
||||
--- a/drivers/pinctrl/meson/pinctrl-meson.c
|
||||
+++ b/drivers/pinctrl/meson/pinctrl-meson.c
|
||||
@@ -557,22 +557,10 @@ static int meson_gpiolib_register(struct meson_pinctrl *pc)
|
||||
if (ret) {
|
||||
dev_err(pc->dev, "can't add gpio chip %s\n",
|
||||
pc->data->name);
|
||||
- goto fail;
|
||||
- }
|
||||
-
|
||||
- ret = gpiochip_add_pin_range(&pc->chip, dev_name(pc->dev),
|
||||
- 0, pc->data->pin_base,
|
||||
- pc->chip.ngpio);
|
||||
- if (ret) {
|
||||
- dev_err(pc->dev, "can't add pin range\n");
|
||||
- goto fail;
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
-fail:
|
||||
- gpiochip_remove(&pc->chip);
|
||||
-
|
||||
- return ret;
|
||||
}
|
||||
|
||||
static struct regmap_config meson_regmap_config = {
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
From 58d7c939ec531f768b03b0be2a714805a6aac3cf Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Thu, 16 Mar 2017 09:40:48 +0100
|
||||
Subject: [PATCH 03/93] ARM64: dts: meson-gxbb: Add USB Hub GPIO hog
|
||||
|
||||
---
|
||||
arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
|
||||
index c59403a..492ac35 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
|
||||
@@ -177,6 +177,15 @@
|
||||
pinctrl-names = "default";
|
||||
};
|
||||
|
||||
+&gpio_ao {
|
||||
+ usb-hub {
|
||||
+ gpio-hog;
|
||||
+ gpios = <GPIOAO_4 GPIO_ACTIVE_HIGH>;
|
||||
+ output-high;
|
||||
+ line-name = "usb-hub-reset";
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
&usb0_phy {
|
||||
status = "okay";
|
||||
phy-supply = <&usb_otg_pwr>;
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
From cbe0dba01d39c008cff6460bfcb1366801b4a41c Mon Sep 17 00:00:00 2001
|
||||
From: Xinliang Liu <xinliang.liu@linaro.org>
|
||||
Date: Wed, 15 Feb 2017 17:19:08 +0100
|
||||
Subject: [PATCH 04/93] drm/fb-helper: Add multi buffer support for cma fbdev
|
||||
|
||||
This patch add a config to support to create multi buffer for cma fbdev.
|
||||
Such as double buffer and triple buffer.
|
||||
|
||||
Cma fbdev is convient to add a legency fbdev. And still many Android
|
||||
devices use fbdev now and at least double buffer is needed for these
|
||||
Android devices, so that a buffer flip can be operated. It will need
|
||||
some time for Android device vendors to abondon legency fbdev. So multi
|
||||
buffer for fbdev is needed.
|
||||
|
||||
Signed-off-by: Xinliang Liu <xinliang.liu@linaro.org>
|
||||
[s.christ@phytec.de: Picking patch from
|
||||
https://lkml.org/lkml/2015/9/14/188]
|
||||
Signed-off-by: Stefan Christ <s.christ@phytec.de>
|
||||
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
|
||||
---
|
||||
drivers/gpu/drm/Kconfig | 9 +++++++++
|
||||
drivers/gpu/drm/drm_fb_helper.c | 10 ++++++++++
|
||||
2 files changed, 19 insertions(+)
|
||||
|
||||
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
|
||||
index ebfe840..700c8b8 100644
|
||||
--- a/drivers/gpu/drm/Kconfig
|
||||
+++ b/drivers/gpu/drm/Kconfig
|
||||
@@ -84,6 +84,15 @@ config DRM_FBDEV_EMULATION
|
||||
|
||||
If in doubt, say "Y".
|
||||
|
||||
+config DRM_FBDEV_OVERALLOC
|
||||
+ int "Overallocation of the fbdev buffer"
|
||||
+ depends on DRM_FBDEV_EMULATION
|
||||
+ default 100
|
||||
+ help
|
||||
+ Defines the fbdev buffer overallocation in percent. Default
|
||||
+ is 100. Typical values for double buffering will be 200,
|
||||
+ triple buffering 300.
|
||||
+
|
||||
config DRM_LOAD_EDID_FIRMWARE
|
||||
bool "Allow to specify an EDID data set instead of probing for it"
|
||||
depends on DRM_KMS_HELPER
|
||||
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
|
||||
index e934b54..c6de87a 100644
|
||||
--- a/drivers/gpu/drm/drm_fb_helper.c
|
||||
+++ b/drivers/gpu/drm/drm_fb_helper.c
|
||||
@@ -48,6 +48,12 @@
|
||||
MODULE_PARM_DESC(fbdev_emulation,
|
||||
"Enable legacy fbdev emulation [default=true]");
|
||||
|
||||
+static int drm_fbdev_overalloc = CONFIG_DRM_FBDEV_OVERALLOC;
|
||||
+module_param(drm_fbdev_overalloc, int, 0444);
|
||||
+MODULE_PARM_DESC(drm_fbdev_overalloc,
|
||||
+ "Overallocation of the fbdev buffer (%) [default="
|
||||
+ __MODULE_STRING(CONFIG_DRM_FBDEV_OVERALLOC) "]");
|
||||
+
|
||||
static LIST_HEAD(kernel_fb_helper_list);
|
||||
static DEFINE_MUTEX(kernel_fb_helper_lock);
|
||||
|
||||
@@ -1573,6 +1579,10 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
|
||||
sizes.fb_height = sizes.surface_height = 768;
|
||||
}
|
||||
|
||||
+ /* Handle our overallocation */
|
||||
+ sizes.surface_height *= drm_fbdev_overalloc;
|
||||
+ sizes.surface_height /= 100;
|
||||
+
|
||||
/* push down into drivers */
|
||||
ret = (*fb_helper->funcs->fb_probe)(fb_helper, &sizes);
|
||||
if (ret < 0)
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
From c48872078789c6911e47e1c74d2024407c4daa8d Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Christ <s.christ@phytec.de>
|
||||
Date: Wed, 15 Feb 2017 17:19:09 +0100
|
||||
Subject: [PATCH 05/93] drm/fb-helper: implement ioctl FBIO_WAITFORVSYNC
|
||||
|
||||
Implement legacy framebuffer ioctl FBIO_WAITFORVSYNC in the generic
|
||||
framebuffer emulation driver. Legacy framebuffer users like non kms/drm
|
||||
based OpenGL(ES)/EGL implementations may require the ioctl to
|
||||
synchronize drawing or buffer flip for double buffering. It is tested on
|
||||
the i.MX6.
|
||||
|
||||
Code is based on
|
||||
https://github.com/Xilinx/linux-xlnx/blob/master/drivers/gpu/drm/xilinx/xilinx_drm_fb.c#L196
|
||||
|
||||
Signed-off-by: Stefan Christ <s.christ@phytec.de>
|
||||
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
|
||||
---
|
||||
drivers/gpu/drm/drm_fb_helper.c | 63 +++++++++++++++++++++++++++++++++++++++++
|
||||
include/drm/drm_fb_helper.h | 12 +++++++-
|
||||
2 files changed, 74 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
|
||||
index c6de87a..15ee964 100644
|
||||
--- a/drivers/gpu/drm/drm_fb_helper.c
|
||||
+++ b/drivers/gpu/drm/drm_fb_helper.c
|
||||
@@ -1240,6 +1240,69 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
|
||||
EXPORT_SYMBOL(drm_fb_helper_setcmap);
|
||||
|
||||
/**
|
||||
+ * drm_fb_helper_ioctl - legacy ioctl implementation
|
||||
+ * @info: fbdev registered by the helper
|
||||
+ * @cmd: ioctl command
|
||||
+ * @arg: ioctl argument
|
||||
+ *
|
||||
+ * A helper to implement the standard fbdev ioctl. Only
|
||||
+ * FBIO_WAITFORVSYNC is implemented for now.
|
||||
+ */
|
||||
+int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
|
||||
+ unsigned long arg)
|
||||
+{
|
||||
+ struct drm_fb_helper *fb_helper = info->par;
|
||||
+ struct drm_device *dev = fb_helper->dev;
|
||||
+ struct drm_mode_set *mode_set;
|
||||
+ struct drm_crtc *crtc;
|
||||
+ u32 karg;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ mutex_lock(&dev->mode_config.mutex);
|
||||
+ if (!drm_fb_helper_is_bound(fb_helper)) {
|
||||
+ ret = -EBUSY;
|
||||
+ goto unlock;
|
||||
+ }
|
||||
+
|
||||
+ switch (cmd) {
|
||||
+ case FBIO_WAITFORVSYNC:
|
||||
+ if (get_user(karg, (__u32 __user *)arg)) {
|
||||
+ ret = -EFAULT;
|
||||
+ goto unlock;
|
||||
+ }
|
||||
+
|
||||
+ if (karg >= fb_helper->crtc_count) {
|
||||
+ ret = -EINVAL;
|
||||
+ goto unlock;
|
||||
+ }
|
||||
+
|
||||
+ mode_set = &fb_helper->crtc_info[karg].mode_set;
|
||||
+ crtc = mode_set->crtc;
|
||||
+
|
||||
+ /*
|
||||
+ * Only wait for a vblank event if the CRTC is
|
||||
+ * enabled, otherwise just don't do anythintg,
|
||||
+ * not even report an error.
|
||||
+ */
|
||||
+ ret = drm_crtc_vblank_get(crtc);
|
||||
+ if (!ret) {
|
||||
+ drm_crtc_wait_one_vblank(crtc);
|
||||
+ drm_crtc_vblank_put(crtc);
|
||||
+ }
|
||||
+
|
||||
+ ret = 0;
|
||||
+ goto unlock;
|
||||
+ default:
|
||||
+ ret = -ENOTTY;
|
||||
+ }
|
||||
+
|
||||
+unlock:
|
||||
+ mutex_unlock(&dev->mode_config.mutex);
|
||||
+ return ret;
|
||||
+}
|
||||
+EXPORT_SYMBOL(drm_fb_helper_ioctl);
|
||||
+
|
||||
+/**
|
||||
* drm_fb_helper_check_var - implementation for ->fb_check_var
|
||||
* @var: screeninfo to check
|
||||
* @info: fbdev registered by the helper
|
||||
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
|
||||
index 975deed..2891888 100644
|
||||
--- a/include/drm/drm_fb_helper.h
|
||||
+++ b/include/drm/drm_fb_helper.h
|
||||
@@ -230,7 +230,8 @@ struct drm_fb_helper {
|
||||
.fb_blank = drm_fb_helper_blank, \
|
||||
.fb_pan_display = drm_fb_helper_pan_display, \
|
||||
.fb_debug_enter = drm_fb_helper_debug_enter, \
|
||||
- .fb_debug_leave = drm_fb_helper_debug_leave
|
||||
+ .fb_debug_leave = drm_fb_helper_debug_leave, \
|
||||
+ .fb_ioctl = drm_fb_helper_ioctl
|
||||
|
||||
#ifdef CONFIG_DRM_FBDEV_EMULATION
|
||||
void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
|
||||
@@ -286,6 +287,9 @@ void drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper,
|
||||
|
||||
int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info);
|
||||
|
||||
+int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
|
||||
+ unsigned long arg);
|
||||
+
|
||||
int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper);
|
||||
int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel);
|
||||
int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper);
|
||||
@@ -377,6 +381,12 @@ static inline int drm_fb_helper_setcmap(struct fb_cmap *cmap,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static inline int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
|
||||
+ unsigned long arg)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static inline void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper)
|
||||
{
|
||||
}
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
From e0c4b1d6b1ac850cb22d574bb485b3cc2ed36903 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Tue, 28 Feb 2017 15:23:14 +0100
|
||||
Subject: [PATCH 06/93] Disable DRM fbdev FBIO_WAITFORVSYNC to achieve full FPS
|
||||
|
||||
---
|
||||
drivers/gpu/drm/drm_fb_helper.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
|
||||
index 15ee964..7b739a8 100644
|
||||
--- a/drivers/gpu/drm/drm_fb_helper.c
|
||||
+++ b/drivers/gpu/drm/drm_fb_helper.c
|
||||
@@ -1266,6 +1266,7 @@ int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
|
||||
|
||||
switch (cmd) {
|
||||
case FBIO_WAITFORVSYNC:
|
||||
+ goto unlock;
|
||||
if (get_user(karg, (__u32 __user *)arg)) {
|
||||
ret = -EFAULT;
|
||||
goto unlock;
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,442 @@
|
|||
From bc80d5294931d37c19ef76d0a1bb144ad51b66f9 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Wed, 1 Feb 2017 11:45:04 +0100
|
||||
Subject: [PATCH 07/93] clk: meson-gxbb: Add MALI clocks and fix GP0 pll
|
||||
support
|
||||
|
||||
The Mali is clocked by two identical clock paths behind a glitch free mux
|
||||
to safely change frequency while running.
|
||||
|
||||
The optimal clock frequency is provided by the GP0 PLL, but unlike Meson8 the
|
||||
GXBB GP0 PLL needs some tweaking and need some SoC specific values to be set
|
||||
in order to setup the PLL.
|
||||
|
||||
Since these values will change for GXL and GXM, add an init table that will
|
||||
be changed for GXL or GXM.
|
||||
|
||||
For the MALI clocks, introduce them as Composite clocks to simplify the
|
||||
management.
|
||||
To handle composite clocks, a gxbb_composite structure is added to dynamically
|
||||
create the composite clock at probe and fill accordingly the DT table.
|
||||
|
||||
Finally the glitch free mux is added and other muxes and dividers are also
|
||||
grouped in initialization tables.
|
||||
---
|
||||
drivers/clk/meson/clk-pll.c | 34 ++++--
|
||||
drivers/clk/meson/clkc.h | 3 +
|
||||
drivers/clk/meson/gxbb.c | 211 +++++++++++++++++++++++++++++++++-
|
||||
drivers/clk/meson/gxbb.h | 7 +-
|
||||
include/dt-bindings/clock/gxbb-clkc.h | 4 +
|
||||
5 files changed, 245 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
|
||||
index 4adc1e8..b5ff81b 100644
|
||||
--- a/drivers/clk/meson/clk-pll.c
|
||||
+++ b/drivers/clk/meson/clk-pll.c
|
||||
@@ -132,6 +132,24 @@ static int meson_clk_pll_wait_lock(struct meson_clk_pll *pll,
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
+static void meson_clk_pll_init(struct meson_clk_pll *pll)
|
||||
+{
|
||||
+ if (pll->init_count && pll->init_regs && pll->init_data) {
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ for (i = 0; i < pll->init_count; ++i)
|
||||
+ writel(pll->init_data[i], pll->init_regs[i]);
|
||||
+ } else {
|
||||
+ struct parm *p;
|
||||
+ u32 reg;
|
||||
+
|
||||
+ /* PLL reset */
|
||||
+ p = &pll->n;
|
||||
+ reg = readl(pll->base + p->reg_off);
|
||||
+ writel(reg | MESON_PLL_RESET, pll->base + p->reg_off);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
@@ -151,19 +169,18 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
if (!rate_set)
|
||||
return -EINVAL;
|
||||
|
||||
- /* PLL reset */
|
||||
- p = &pll->n;
|
||||
- reg = readl(pll->base + p->reg_off);
|
||||
- writel(reg | MESON_PLL_RESET, pll->base + p->reg_off);
|
||||
-
|
||||
- reg = PARM_SET(p->width, p->shift, reg, rate_set->n);
|
||||
- writel(reg, pll->base + p->reg_off);
|
||||
+ meson_clk_pll_init(pll);
|
||||
|
||||
p = &pll->m;
|
||||
reg = readl(pll->base + p->reg_off);
|
||||
reg = PARM_SET(p->width, p->shift, reg, rate_set->m);
|
||||
writel(reg, pll->base + p->reg_off);
|
||||
|
||||
+ p = &pll->n;
|
||||
+ reg = readl(pll->base + p->reg_off);
|
||||
+ reg = PARM_SET(p->width, p->shift, reg, rate_set->n);
|
||||
+ writel(reg, pll->base + p->reg_off);
|
||||
+
|
||||
p = &pll->od;
|
||||
reg = readl(pll->base + p->reg_off);
|
||||
reg = PARM_SET(p->width, p->shift, reg, rate_set->od);
|
||||
@@ -184,6 +201,9 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
}
|
||||
|
||||
p = &pll->n;
|
||||
+ reg = readl(pll->base + p->reg_off);
|
||||
+ writel(reg & ~MESON_PLL_RESET, pll->base + p->reg_off);
|
||||
+
|
||||
ret = meson_clk_pll_wait_lock(pll, p);
|
||||
if (ret) {
|
||||
pr_warn("%s: pll did not lock, trying to restore old rate %lu\n",
|
||||
diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
|
||||
index 9bb70e7..22a6335 100644
|
||||
--- a/drivers/clk/meson/clkc.h
|
||||
+++ b/drivers/clk/meson/clkc.h
|
||||
@@ -70,6 +70,9 @@ struct meson_clk_pll {
|
||||
struct parm frac;
|
||||
struct parm od;
|
||||
struct parm od2;
|
||||
+ void __iomem **init_regs;
|
||||
+ u32 *init_data;
|
||||
+ unsigned int init_count;
|
||||
const struct pll_rate_table *rate_table;
|
||||
unsigned int rate_count;
|
||||
spinlock_t *lock;
|
||||
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
|
||||
index 9d9af44..d1dac0f 100644
|
||||
--- a/drivers/clk/meson/gxbb.c
|
||||
+++ b/drivers/clk/meson/gxbb.c
|
||||
@@ -352,6 +352,20 @@
|
||||
},
|
||||
};
|
||||
|
||||
+static void __iomem *gxbb_gp0_init_regs[] = {
|
||||
+ (void *)HHI_GP0_PLL_CNTL,
|
||||
+ (void *)HHI_GP0_PLL_CNTL2,
|
||||
+ (void *)HHI_GP0_PLL_CNTL3,
|
||||
+ (void *)HHI_GP0_PLL_CNTL4,
|
||||
+};
|
||||
+
|
||||
+static u32 gxbb_gp0_init_data[] = {
|
||||
+ 0x6a000228,
|
||||
+ 0x69c80000,
|
||||
+ 0x0a5590c4,
|
||||
+ 0x0000500d,
|
||||
+};
|
||||
+
|
||||
static struct meson_clk_pll gxbb_gp0_pll = {
|
||||
.m = {
|
||||
.reg_off = HHI_GP0_PLL_CNTL,
|
||||
@@ -368,6 +382,9 @@
|
||||
.shift = 16,
|
||||
.width = 2,
|
||||
},
|
||||
+ .init_regs = gxbb_gp0_init_regs,
|
||||
+ .init_data = gxbb_gp0_init_data,
|
||||
+ .init_count = 4,
|
||||
.rate_table = gp0_pll_rate_table,
|
||||
.rate_count = ARRAY_SIZE(gp0_pll_rate_table),
|
||||
.lock = &clk_lock,
|
||||
@@ -550,6 +567,75 @@
|
||||
},
|
||||
};
|
||||
|
||||
+/* Mali Clock components */
|
||||
+static u32 mux_table_mali_0_1[] = {0, 1, 2, 3, 4, 5, 6, 7};
|
||||
+const char *gxbb_mali_0_1_parent_names[] = {
|
||||
+ "xtal", "gp0_pll", "mpll2", "mpll1", "fclk_div7",
|
||||
+ "fclk_div4", "fclk_div3", "fclk_div5"
|
||||
+};
|
||||
+
|
||||
+static struct clk_mux gxbb_mali_0_sel = {
|
||||
+ .reg = (void *)HHI_MALI_CLK_CNTL,
|
||||
+ .mask = 0x3,
|
||||
+ .shift = 9,
|
||||
+ .table = mux_table_mali_0_1,
|
||||
+ .lock = &clk_lock,
|
||||
+};
|
||||
+
|
||||
+static struct clk_divider gxbb_mali_0_div = {
|
||||
+ .reg = (void *)HHI_MALI_CLK_CNTL,
|
||||
+ .shift = 0,
|
||||
+ .width = 7,
|
||||
+ .lock = &clk_lock,
|
||||
+};
|
||||
+
|
||||
+static struct clk_gate gxbb_mali_0_en = {
|
||||
+ .reg = (void *)HHI_MALI_CLK_CNTL,
|
||||
+ .bit_idx = 8,
|
||||
+ .lock = &clk_lock,
|
||||
+};
|
||||
+
|
||||
+static struct clk_mux gxbb_mali_1_sel = {
|
||||
+ .reg = (void *)HHI_MALI_CLK_CNTL,
|
||||
+ .mask = 0x3,
|
||||
+ .shift = 25,
|
||||
+ .table = mux_table_mali_0_1,
|
||||
+ .lock = &clk_lock,
|
||||
+};
|
||||
+
|
||||
+static struct clk_divider gxbb_mali_1_div = {
|
||||
+ .reg = (void *)HHI_MALI_CLK_CNTL,
|
||||
+ .shift = 16,
|
||||
+ .width = 7,
|
||||
+ .lock = &clk_lock,
|
||||
+};
|
||||
+
|
||||
+static struct clk_gate gxbb_mali_1_en = {
|
||||
+ .reg = (void *)HHI_MALI_CLK_CNTL,
|
||||
+ .bit_idx = 24,
|
||||
+ .lock = &clk_lock,
|
||||
+};
|
||||
+
|
||||
+static u32 mux_table_mali[] = {0, 1};
|
||||
+const char *gxbb_mali_parent_names[] = {
|
||||
+ "mali_0", "mali_1"
|
||||
+};
|
||||
+
|
||||
+static struct clk_mux gxbb_mali = {
|
||||
+ .reg = (void *)HHI_MALI_CLK_CNTL,
|
||||
+ .mask = 1,
|
||||
+ .shift = 31,
|
||||
+ .table = mux_table_mali,
|
||||
+ .lock = &clk_lock,
|
||||
+ .hw.init = &(struct clk_init_data){
|
||||
+ .name = "mali",
|
||||
+ .ops = &clk_mux_ops,
|
||||
+ .parent_names = gxbb_mali_parent_names,
|
||||
+ .num_parents = 2,
|
||||
+ .flags = (CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED),
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
/* the mother of dragons^W gates */
|
||||
static struct clk_gate gxbb_clk81 = {
|
||||
.reg = (void *)HHI_MPEG_CLK_CNTL,
|
||||
@@ -754,6 +840,9 @@
|
||||
[CLKID_SD_EMMC_A] = &gxbb_emmc_a.hw,
|
||||
[CLKID_SD_EMMC_B] = &gxbb_emmc_b.hw,
|
||||
[CLKID_SD_EMMC_C] = &gxbb_emmc_c.hw,
|
||||
+ [CLKID_MALI] = &gxbb_mali.hw,
|
||||
+ /* This sentinel entry makes sure the table is large enough */
|
||||
+ [NR_CLKS] = NULL, /* Sentinel */
|
||||
},
|
||||
.num = NR_CLKS,
|
||||
};
|
||||
@@ -856,6 +945,66 @@
|
||||
&gxbb_emmc_a,
|
||||
&gxbb_emmc_b,
|
||||
&gxbb_emmc_c,
|
||||
+ &gxbb_mali_0_en,
|
||||
+ &gxbb_mali_1_en,
|
||||
+};
|
||||
+
|
||||
+static struct clk_mux *gxbb_clk_muxes[] = {
|
||||
+ &gxbb_mpeg_clk_sel,
|
||||
+ &gxbb_mali_0_sel,
|
||||
+ &gxbb_mali_1_sel,
|
||||
+ &gxbb_mali,
|
||||
+};
|
||||
+
|
||||
+static struct clk_divider *gxbb_clk_dividers[] = {
|
||||
+ &gxbb_mpeg_clk_div,
|
||||
+ &gxbb_mali_0_div,
|
||||
+ &gxbb_mali_1_div,
|
||||
+};
|
||||
+
|
||||
+struct gxbb_composite_clk {
|
||||
+ unsigned int id;
|
||||
+ const char *name;
|
||||
+ const char * const *parent_names;
|
||||
+ int num_parents;
|
||||
+ struct clk_hw *mux_hw;
|
||||
+ const struct clk_ops *mux_ops;
|
||||
+ struct clk_hw *rate_hw;
|
||||
+ const struct clk_ops *rate_ops;
|
||||
+ struct clk_hw *gate_hw;
|
||||
+ const struct clk_ops *gate_ops;
|
||||
+ unsigned long flags;
|
||||
+};
|
||||
+
|
||||
+/* Convenient table to register the composite clocks */
|
||||
+
|
||||
+static struct gxbb_composite_clk gxbb_composite_clks[] = {
|
||||
+ {
|
||||
+ .id = CLKID_MALI_0,
|
||||
+ .name = "mali_0",
|
||||
+ .parent_names = gxbb_mali_0_1_parent_names,
|
||||
+ .num_parents = ARRAY_SIZE(gxbb_mali_0_1_parent_names),
|
||||
+ .mux_hw = &gxbb_mali_0_sel.hw,
|
||||
+ .mux_ops = &clk_mux_ops,
|
||||
+ .rate_hw = &gxbb_mali_0_div.hw,
|
||||
+ .rate_ops = &clk_divider_ops,
|
||||
+ .gate_hw = &gxbb_mali_0_en.hw,
|
||||
+ .gate_ops = &clk_gate_ops,
|
||||
+ .flags = (CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED),
|
||||
+ },
|
||||
+ {
|
||||
+ .id = CLKID_MALI_1,
|
||||
+ .name = "mali_1",
|
||||
+ .parent_names = gxbb_mali_0_1_parent_names,
|
||||
+ .num_parents = ARRAY_SIZE(gxbb_mali_0_1_parent_names),
|
||||
+ .mux_hw = &gxbb_mali_1_sel.hw,
|
||||
+ .mux_ops = &clk_mux_ops,
|
||||
+ .rate_hw = &gxbb_mali_1_div.hw,
|
||||
+ .rate_ops = &clk_divider_ops,
|
||||
+ .gate_hw = &gxbb_mali_1_en.hw,
|
||||
+ .gate_ops = &clk_gate_ops,
|
||||
+ .flags = (CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED),
|
||||
+ },
|
||||
};
|
||||
|
||||
static int gxbb_clkc_probe(struct platform_device *pdev)
|
||||
@@ -884,24 +1033,61 @@ static int gxbb_clkc_probe(struct platform_device *pdev)
|
||||
/* Populate the base address for CPU clk */
|
||||
gxbb_cpu_clk.base = clk_base;
|
||||
|
||||
- /* Populate the base address for the MPEG clks */
|
||||
- gxbb_mpeg_clk_sel.reg = clk_base + (u64)gxbb_mpeg_clk_sel.reg;
|
||||
- gxbb_mpeg_clk_div.reg = clk_base + (u64)gxbb_mpeg_clk_div.reg;
|
||||
+ /* Populate base address for muxes */
|
||||
+ for (i = 0; i < ARRAY_SIZE(gxbb_clk_muxes); i++)
|
||||
+ gxbb_clk_muxes[i]->reg = clk_base +
|
||||
+ (u64)gxbb_clk_muxes[i]->reg;
|
||||
+
|
||||
+ /* Populate base address for dividers */
|
||||
+ for (i = 0; i < ARRAY_SIZE(gxbb_clk_dividers); i++)
|
||||
+ gxbb_clk_dividers[i]->reg = clk_base +
|
||||
+ (u64)gxbb_clk_dividers[i]->reg;
|
||||
|
||||
/* Populate base address for gates */
|
||||
for (i = 0; i < ARRAY_SIZE(gxbb_clk_gates); i++)
|
||||
gxbb_clk_gates[i]->reg = clk_base +
|
||||
(u64)gxbb_clk_gates[i]->reg;
|
||||
|
||||
+ /* Populate base for GP0 init table */
|
||||
+ for (i = 0; i < ARRAY_SIZE(gxbb_gp0_init_regs); ++i)
|
||||
+ gxbb_gp0_init_regs[i] = clk_base +
|
||||
+ (u64)gxbb_gp0_init_regs[i];
|
||||
+
|
||||
/*
|
||||
* register all clks
|
||||
*/
|
||||
for (clkid = 0; clkid < NR_CLKS; clkid++) {
|
||||
+ if (!gxbb_hw_onecell_data.hws[clkid])
|
||||
+ continue;
|
||||
+
|
||||
ret = devm_clk_hw_register(dev, gxbb_hw_onecell_data.hws[clkid]);
|
||||
if (ret)
|
||||
goto iounmap;
|
||||
}
|
||||
|
||||
+ /* Register Composite Clocks */
|
||||
+ for (i = 0 ; i < ARRAY_SIZE(gxbb_composite_clks); ++i) {
|
||||
+ struct gxbb_composite_clk *comp = &gxbb_composite_clks[i];
|
||||
+ struct clk_hw *hw;
|
||||
+
|
||||
+ hw = clk_hw_register_composite(dev, comp->name,
|
||||
+ comp->parent_names,
|
||||
+ comp->num_parents,
|
||||
+ comp->mux_hw, comp->mux_ops,
|
||||
+ comp->rate_hw, comp->rate_ops,
|
||||
+ comp->gate_hw, comp->gate_ops,
|
||||
+ comp->flags);
|
||||
+ if (IS_ERR(hw)) {
|
||||
+ ret = PTR_ERR(hw);
|
||||
+
|
||||
+ pr_err("%s: Failed to register composite clock %s\n",
|
||||
+ __func__, comp->name);
|
||||
+
|
||||
+ goto unregister_composites;
|
||||
+ }
|
||||
+ gxbb_hw_onecell_data.hws[comp->id] = hw;
|
||||
+ }
|
||||
+
|
||||
/*
|
||||
* Register CPU clk notifier
|
||||
*
|
||||
@@ -922,11 +1108,26 @@ static int gxbb_clkc_probe(struct platform_device *pdev)
|
||||
if (ret) {
|
||||
pr_err("%s: failed to register clock notifier for cpu_clk\n",
|
||||
__func__);
|
||||
- goto iounmap;
|
||||
+ goto unregister_composites;
|
||||
}
|
||||
|
||||
- return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
|
||||
+ ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
|
||||
&gxbb_hw_onecell_data);
|
||||
+ if (!ret)
|
||||
+ return ret;
|
||||
+
|
||||
+unregister_composites:
|
||||
+ for (i = 0 ; i < ARRAY_SIZE(gxbb_composite_clks); ++i) {
|
||||
+ struct gxbb_composite_clk *comp = &gxbb_composite_clks[i];
|
||||
+ struct clk *clk;
|
||||
+
|
||||
+ if (gxbb_hw_onecell_data.hws[comp->id]) {
|
||||
+ clk = gxbb_hw_onecell_data.hws[comp->id]->clk;
|
||||
+ clk_unregister_composite(clk);
|
||||
+ }
|
||||
+
|
||||
+ gxbb_hw_onecell_data.hws[comp->id] = NULL;
|
||||
+ }
|
||||
|
||||
iounmap:
|
||||
iounmap(clk_base);
|
||||
diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h
|
||||
index 0252939..f79ab57 100644
|
||||
--- a/drivers/clk/meson/gxbb.h
|
||||
+++ b/drivers/clk/meson/gxbb.h
|
||||
@@ -177,7 +177,7 @@
|
||||
/* CLKID_FCLK_DIV4 */
|
||||
#define CLKID_FCLK_DIV5 7
|
||||
#define CLKID_FCLK_DIV7 8
|
||||
-#define CLKID_GP0_PLL 9
|
||||
+/* CLKID_GP0_PLL */
|
||||
#define CLKID_MPEG_SEL 10
|
||||
#define CLKID_MPEG_DIV 11
|
||||
/* CLKID_CLK81 */
|
||||
@@ -265,8 +265,11 @@
|
||||
/* CLKID_SD_EMMC_A */
|
||||
/* CLKID_SD_EMMC_B */
|
||||
/* CLKID_SD_EMMC_C */
|
||||
+/* CLKID_MALI_0 */
|
||||
+/* CLKID_MALI_1 */
|
||||
+/* CLKID_MALI */
|
||||
|
||||
-#define NR_CLKS 97
|
||||
+#define NR_CLKS 100
|
||||
|
||||
/* include the CLKIDs that have been made part of the stable DT binding */
|
||||
#include <dt-bindings/clock/gxbb-clkc.h>
|
||||
diff --git a/include/dt-bindings/clock/gxbb-clkc.h b/include/dt-bindings/clock/gxbb-clkc.h
|
||||
index baade6f..7bbc1d0 100644
|
||||
--- a/include/dt-bindings/clock/gxbb-clkc.h
|
||||
+++ b/include/dt-bindings/clock/gxbb-clkc.h
|
||||
@@ -10,6 +10,7 @@
|
||||
#define CLKID_FCLK_DIV2 4
|
||||
#define CLKID_FCLK_DIV3 5
|
||||
#define CLKID_FCLK_DIV4 6
|
||||
+#define CLKID_GP0_PLL 9
|
||||
#define CLKID_CLK81 12
|
||||
#define CLKID_MPLL2 15
|
||||
#define CLKID_SPI 34
|
||||
@@ -24,5 +25,8 @@
|
||||
#define CLKID_SD_EMMC_A 94
|
||||
#define CLKID_SD_EMMC_B 95
|
||||
#define CLKID_SD_EMMC_C 96
|
||||
+#define CLKID_MALI_0 97
|
||||
+#define CLKID_MALI_1 98
|
||||
+#define CLKID_MALI 99
|
||||
|
||||
#endif /* __GXBB_CLKC_H */
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
From 992ae3b904d0ace47dcf33f8cc117a17f1cff0c2 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Wed, 1 Feb 2017 11:45:40 +0100
|
||||
Subject: [PATCH 08/93] ARM64: dts: meson-gxbb: Add Mali node
|
||||
|
||||
Add the Mali-450 MP3 node for GXBB.
|
||||
---
|
||||
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 37 +++++++++++++++++++++++++++++
|
||||
1 file changed, 37 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
index 2be29a3..bbb034d 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
@@ -476,6 +476,43 @@
|
||||
};
|
||||
};
|
||||
|
||||
+&apb {
|
||||
+ mali: gpu@c0000 {
|
||||
+ compatible = "amlogic,meson-gxbb-mali", "arm,mali-450";
|
||||
+ reg = <0x0 0xc0000 0x0 0x40000>;
|
||||
+ interrupts = <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ interrupt-names = "gp", "gpmmu", "pp", "pmu",
|
||||
+ "pp0", "ppmmu0", "pp1", "ppmmu1",
|
||||
+ "pp2", "ppmmu2";
|
||||
+ clocks = <&clkc CLKID_CLK81>, <&clkc CLKID_MALI>;
|
||||
+ clock-names = "bus", "core";
|
||||
+
|
||||
+ /*
|
||||
+ * Mali clocking is provided by two identical clock paths
|
||||
+ * MALI_0 and MALI_1 muxed to a single clock by a glitch
|
||||
+ * free mux to safely change frequency while running.
|
||||
+ */
|
||||
+ assigned-clocks = <&clkc CLKID_GP0_PLL>,
|
||||
+ <&clkc CLKID_MALI_0>,
|
||||
+ <&clkc CLKID_MALI>; /* Glitch free mux */
|
||||
+ assigned-clock-parents = <0>, /* Do Nothing */
|
||||
+ <&clkc CLKID_GP0_PLL>,
|
||||
+ <&clkc CLKID_MALI_0>;
|
||||
+ assigned-clock-rates = <744000000>,
|
||||
+ <744000000>,
|
||||
+ <0>; /* Do Nothing */
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
&i2c_A {
|
||||
clocks = <&clkc CLKID_I2C>;
|
||||
};
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,212 @@
|
|||
From d7efc514cff47e958849fa122bc81839541b3dba Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Wed, 18 Jan 2017 10:33:04 +0100
|
||||
Subject: [PATCH 09/93] ARM64: dts: meson-gxbb: Add support for WeTek Hub and
|
||||
Play
|
||||
|
||||
Adds support for the WeTek Hub and Play2 boards.
|
||||
The Hub is an extremely small IPTv Set-Top-Box and the Play2 is a more
|
||||
traditionnal Satellite or Terrestrial and IPTv Set-Top-Box.
|
||||
|
||||
Both are based on the p200 Reference Design and out-of-tree support is
|
||||
based on OpenELEC kernel at [1].
|
||||
|
||||
[1] https://github.com/wetek-enigma/linux-amlogic
|
||||
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
arch/arm64/boot/dts/amlogic/Makefile | 2 +
|
||||
.../boot/dts/amlogic/meson-gxbb-wetek-hub.dts | 66 +++++++++++++++
|
||||
.../boot/dts/amlogic/meson-gxbb-wetek-play2.dts | 94 ++++++++++++++++++++++
|
||||
3 files changed, 162 insertions(+)
|
||||
create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts
|
||||
create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile
|
||||
index 0d7bfbf..cc2e2dd 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/Makefile
|
||||
+++ b/arch/arm64/boot/dts/amlogic/Makefile
|
||||
@@ -5,6 +5,8 @@ dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-p201.dtb
|
||||
dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-vega-s95-pro.dtb
|
||||
dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-vega-s95-meta.dtb
|
||||
dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-vega-s95-telos.dtb
|
||||
+dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-wetek-hub.dtb
|
||||
+dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-wetek-play2.dtb
|
||||
dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-p212.dtb
|
||||
dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-p230.dtb
|
||||
dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-p231.dtb
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts
|
||||
new file mode 100644
|
||||
index 0000000..56f8559
|
||||
--- /dev/null
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts
|
||||
@@ -0,0 +1,66 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2016 BayLibre, Inc.
|
||||
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
|
||||
+ *
|
||||
+ * This file is dual-licensed: you can use it either under the terms
|
||||
+ * of the GPL or the X11 license, at your option. Note that this dual
|
||||
+ * licensing only applies to this file, and not this project as a
|
||||
+ * whole.
|
||||
+ *
|
||||
+ * a) This library is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation; either version 2 of the
|
||||
+ * License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * This library is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * Or, alternatively,
|
||||
+ *
|
||||
+ * b) Permission is hereby granted, free of charge, to any person
|
||||
+ * obtaining a copy of this software and associated documentation
|
||||
+ * files (the "Software"), to deal in the Software without
|
||||
+ * restriction, including without limitation the rights to use,
|
||||
+ * copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
+ * sell copies of the Software, and to permit persons to whom the
|
||||
+ * Software is furnished to do so, subject to the following
|
||||
+ * conditions:
|
||||
+ *
|
||||
+ * The above copyright notice and this permission notice shall be
|
||||
+ * included in all copies or substantial portions of the Software.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
+ * OTHER DEALINGS IN THE SOFTWARE.
|
||||
+ */
|
||||
+
|
||||
+/dts-v1/;
|
||||
+
|
||||
+#include "meson-gxbb-p20x.dtsi"
|
||||
+
|
||||
+/ {
|
||||
+ compatible = "wetek,hub", "amlogic,meson-gxbb";
|
||||
+ model = "WeTek Hub";
|
||||
+
|
||||
+ leds {
|
||||
+ compatible = "gpio-leds";
|
||||
+
|
||||
+ system {
|
||||
+ label = "wetek-play:system-status";
|
||||
+ gpios = <&gpio_ao GPIOAO_13 GPIO_ACTIVE_HIGH>;
|
||||
+ default-state = "on";
|
||||
+ panic-indicator;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ cvbs-connector {
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+};
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts
|
||||
new file mode 100644
|
||||
index 0000000..ea79fdd
|
||||
--- /dev/null
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts
|
||||
@@ -0,0 +1,94 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2016 BayLibre, Inc.
|
||||
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
|
||||
+ *
|
||||
+ * This file is dual-licensed: you can use it either under the terms
|
||||
+ * of the GPL or the X11 license, at your option. Note that this dual
|
||||
+ * licensing only applies to this file, and not this project as a
|
||||
+ * whole.
|
||||
+ *
|
||||
+ * a) This library is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation; either version 2 of the
|
||||
+ * License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * This library is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * Or, alternatively,
|
||||
+ *
|
||||
+ * b) Permission is hereby granted, free of charge, to any person
|
||||
+ * obtaining a copy of this software and associated documentation
|
||||
+ * files (the "Software"), to deal in the Software without
|
||||
+ * restriction, including without limitation the rights to use,
|
||||
+ * copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
+ * sell copies of the Software, and to permit persons to whom the
|
||||
+ * Software is furnished to do so, subject to the following
|
||||
+ * conditions:
|
||||
+ *
|
||||
+ * The above copyright notice and this permission notice shall be
|
||||
+ * included in all copies or substantial portions of the Software.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
+ * OTHER DEALINGS IN THE SOFTWARE.
|
||||
+ */
|
||||
+
|
||||
+/dts-v1/;
|
||||
+
|
||||
+#include "meson-gxbb-p20x.dtsi"
|
||||
+#include <dt-bindings/input/input.h>
|
||||
+
|
||||
+/ {
|
||||
+ compatible = "wetek,play2", "amlogic,meson-gxbb";
|
||||
+ model = "WeTek Play 2";
|
||||
+
|
||||
+ leds {
|
||||
+ compatible = "gpio-leds";
|
||||
+
|
||||
+ system {
|
||||
+ label = "wetek-play:system-status";
|
||||
+ gpios = <&gpio_ao GPIOAO_13 GPIO_ACTIVE_HIGH>;
|
||||
+ default-state = "on";
|
||||
+ panic-indicator;
|
||||
+ };
|
||||
+
|
||||
+ wifi {
|
||||
+ label = "wetek-play:wifi-status";
|
||||
+ gpios = <&gpio GPIODV_26 GPIO_ACTIVE_HIGH>;
|
||||
+ default-state = "off";
|
||||
+ };
|
||||
+
|
||||
+ ethernet {
|
||||
+ label = "wetek-play:ethernet-status";
|
||||
+ gpios = <&gpio GPIODV_27 GPIO_ACTIVE_HIGH>;
|
||||
+ default-state = "off";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ gpio-keys-polled {
|
||||
+ compatible = "gpio-keys-polled";
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
+ poll-interval = <100>;
|
||||
+
|
||||
+ button@0 {
|
||||
+ label = "reset";
|
||||
+ linux,code = <KEY_RESTART>;
|
||||
+ gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_LOW>;
|
||||
+ };
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
+&i2c_A {
|
||||
+ status = "okay";
|
||||
+ pinctrl-0 = <&i2c_a_pins>;
|
||||
+ pinctrl-names = "default";
|
||||
+};
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,639 @@
|
|||
From b53f55423fe344ecdd5bc8b2437170013a0a46e4 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Mon, 28 Nov 2016 17:59:08 +0200
|
||||
Subject: [PATCH 10/93] drm: bridge: Link encoder and bridge in core code
|
||||
|
||||
Instead of linking encoders and bridges in every driver (and getting it
|
||||
wrong half of the time, as many drivers forget to set the drm_bridge
|
||||
encoder pointer), do so in core code. The drm_bridge_attach() function
|
||||
needs the encoder and optional previous bridge to perform that task,
|
||||
update all the callers.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Acked-by: Stefan Agner <stefan@agner.ch> # For DCU
|
||||
Acked-by: Boris Brezillon <boris.brezillon@free-electrons.com> # For atmel-hlcdc
|
||||
Acked-by: Vincent Abriou <vincent.abriou@st.com> # For STI
|
||||
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com> # For sun4i
|
||||
Acked-by: Xinliang Liu <z.liuxinliang@hisilicon.com> # For hisilicon
|
||||
Acked-by: Jyri Sarha <jsarha@ti.com> # For tilcdc
|
||||
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/1481709550-29226-4-git-send-email-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/arc/arcpgu_hdmi.c | 5 +--
|
||||
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c | 4 +-
|
||||
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 4 +-
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 3 +-
|
||||
drivers/gpu/drm/drm_bridge.c | 46 ++++++++++++++++------
|
||||
drivers/gpu/drm/drm_simple_kms_helper.c | 4 +-
|
||||
drivers/gpu/drm/exynos/exynos_dp.c | 5 +--
|
||||
drivers/gpu/drm/exynos/exynos_drm_dsi.c | 6 +--
|
||||
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c | 5 +--
|
||||
drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c | 5 +--
|
||||
drivers/gpu/drm/imx/imx-ldb.c | 6 +--
|
||||
drivers/gpu/drm/imx/parallel-display.c | 4 +-
|
||||
drivers/gpu/drm/mediatek/mtk_dpi.c | 8 ++--
|
||||
drivers/gpu/drm/mediatek/mtk_dsi.c | 24 ++---------
|
||||
drivers/gpu/drm/mediatek/mtk_hdmi.c | 11 +++---
|
||||
drivers/gpu/drm/msm/dsi/dsi_manager.c | 17 +++++---
|
||||
drivers/gpu/drm/msm/edp/edp_bridge.c | 2 +-
|
||||
drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 2 +-
|
||||
drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c | 5 +--
|
||||
drivers/gpu/drm/sti/sti_dvo.c | 3 +-
|
||||
drivers/gpu/drm/sti/sti_hda.c | 3 +-
|
||||
drivers/gpu/drm/sti/sti_hdmi.c | 3 +-
|
||||
drivers/gpu/drm/sun4i/sun4i_rgb.c | 13 +++---
|
||||
drivers/gpu/drm/tilcdc/tilcdc_external.c | 4 +-
|
||||
include/drm/drm_bridge.h | 3 +-
|
||||
25 files changed, 85 insertions(+), 110 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/arc/arcpgu_hdmi.c b/drivers/gpu/drm/arc/arcpgu_hdmi.c
|
||||
index b69c66b..0ce7f39 100644
|
||||
--- a/drivers/gpu/drm/arc/arcpgu_hdmi.c
|
||||
+++ b/drivers/gpu/drm/arc/arcpgu_hdmi.c
|
||||
@@ -47,10 +47,7 @@ int arcpgu_drm_hdmi_init(struct drm_device *drm, struct device_node *np)
|
||||
return ret;
|
||||
|
||||
/* Link drm_bridge to encoder */
|
||||
- bridge->encoder = encoder;
|
||||
- encoder->bridge = bridge;
|
||||
-
|
||||
- ret = drm_bridge_attach(drm, bridge);
|
||||
+ ret = drm_bridge_attach(encoder, bridge, NULL);
|
||||
if (ret)
|
||||
drm_encoder_cleanup(encoder);
|
||||
|
||||
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
|
||||
index 6119b50..e7799b6 100644
|
||||
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
|
||||
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
|
||||
@@ -230,9 +230,7 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
|
||||
of_node_put(np);
|
||||
|
||||
if (bridge) {
|
||||
- output->encoder.bridge = bridge;
|
||||
- bridge->encoder = &output->encoder;
|
||||
- ret = drm_bridge_attach(dev, bridge);
|
||||
+ ret = drm_bridge_attach(&output->encoder, bridge, NULL);
|
||||
if (!ret)
|
||||
return 0;
|
||||
}
|
||||
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
|
||||
index 18eefdc..dfae80f 100644
|
||||
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
|
||||
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
|
||||
@@ -1227,12 +1227,10 @@ static int analogix_dp_create_bridge(struct drm_device *drm_dev,
|
||||
|
||||
dp->bridge = bridge;
|
||||
|
||||
- dp->encoder->bridge = bridge;
|
||||
bridge->driver_private = dp;
|
||||
- bridge->encoder = dp->encoder;
|
||||
bridge->funcs = &analogix_dp_bridge_funcs;
|
||||
|
||||
- ret = drm_bridge_attach(drm_dev, bridge);
|
||||
+ ret = drm_bridge_attach(dp->encoder, bridge, NULL);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to attach drm bridge\n");
|
||||
return -EINVAL;
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 235ce7d..f5009ae 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -1841,13 +1841,12 @@ static int dw_hdmi_register(struct drm_device *drm, struct dw_hdmi *hdmi)
|
||||
hdmi->bridge = bridge;
|
||||
bridge->driver_private = hdmi;
|
||||
bridge->funcs = &dw_hdmi_bridge_funcs;
|
||||
- ret = drm_bridge_attach(drm, bridge);
|
||||
+ ret = drm_bridge_attach(encoder, bridge, NULL);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to initialize bridge with drm\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- encoder->bridge = bridge;
|
||||
hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
|
||||
|
||||
drm_connector_helper_add(&hdmi->connector,
|
||||
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
|
||||
index 0ee052b..850bd65 100644
|
||||
--- a/drivers/gpu/drm/drm_bridge.c
|
||||
+++ b/drivers/gpu/drm/drm_bridge.c
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include <drm/drm_bridge.h>
|
||||
+#include <drm/drm_encoder.h>
|
||||
|
||||
/**
|
||||
* DOC: overview
|
||||
@@ -92,32 +93,53 @@ void drm_bridge_remove(struct drm_bridge *bridge)
|
||||
EXPORT_SYMBOL(drm_bridge_remove);
|
||||
|
||||
/**
|
||||
- * drm_bridge_attach - associate given bridge to our DRM device
|
||||
+ * drm_bridge_attach - attach the bridge to an encoder's chain
|
||||
*
|
||||
- * @dev: DRM device
|
||||
- * @bridge: bridge control structure
|
||||
+ * @encoder: DRM encoder
|
||||
+ * @bridge: bridge to attach
|
||||
+ * @previous: previous bridge in the chain (optional)
|
||||
*
|
||||
- * Called by a kms driver to link one of our encoder/bridge to the given
|
||||
- * bridge.
|
||||
+ * Called by a kms driver to link the bridge to an encoder's chain. The previous
|
||||
+ * argument specifies the previous bridge in the chain. If NULL, the bridge is
|
||||
+ * linked directly at the encoder's output. Otherwise it is linked at the
|
||||
+ * previous bridge's output.
|
||||
*
|
||||
- * Note that setting up links between the bridge and our encoder/bridge
|
||||
- * objects needs to be handled by the kms driver itself.
|
||||
+ * If non-NULL the previous bridge must be already attached by a call to this
|
||||
+ * function.
|
||||
*
|
||||
* RETURNS:
|
||||
* Zero on success, error code on failure
|
||||
*/
|
||||
-int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge)
|
||||
+int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
|
||||
+ struct drm_bridge *previous)
|
||||
{
|
||||
- if (!dev || !bridge)
|
||||
+ int ret;
|
||||
+
|
||||
+ if (!encoder || !bridge)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (previous && (!previous->dev || previous->encoder != encoder))
|
||||
return -EINVAL;
|
||||
|
||||
if (bridge->dev)
|
||||
return -EBUSY;
|
||||
|
||||
- bridge->dev = dev;
|
||||
+ bridge->dev = encoder->dev;
|
||||
+ bridge->encoder = encoder;
|
||||
+
|
||||
+ if (bridge->funcs->attach) {
|
||||
+ ret = bridge->funcs->attach(bridge);
|
||||
+ if (ret < 0) {
|
||||
+ bridge->dev = NULL;
|
||||
+ bridge->encoder = NULL;
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- if (bridge->funcs->attach)
|
||||
- return bridge->funcs->attach(bridge);
|
||||
+ if (previous)
|
||||
+ previous->next = bridge;
|
||||
+ else
|
||||
+ encoder->bridge = bridge;
|
||||
|
||||
return 0;
|
||||
}
|
||||
diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
|
||||
index 7bae08c..ba7be61 100644
|
||||
--- a/drivers/gpu/drm/drm_simple_kms_helper.c
|
||||
+++ b/drivers/gpu/drm/drm_simple_kms_helper.c
|
||||
@@ -182,9 +182,7 @@ static void drm_simple_kms_plane_cleanup_fb(struct drm_plane *plane,
|
||||
int drm_simple_display_pipe_attach_bridge(struct drm_simple_display_pipe *pipe,
|
||||
struct drm_bridge *bridge)
|
||||
{
|
||||
- bridge->encoder = &pipe->encoder;
|
||||
- pipe->encoder.bridge = bridge;
|
||||
- return drm_bridge_attach(pipe->encoder.dev, bridge);
|
||||
+ return drm_bridge_attach(&pipe->encoder, bridge, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_simple_display_pipe_attach_bridge);
|
||||
|
||||
diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c
|
||||
index 528229f..1ef0be3 100644
|
||||
--- a/drivers/gpu/drm/exynos/exynos_dp.c
|
||||
+++ b/drivers/gpu/drm/exynos/exynos_dp.c
|
||||
@@ -99,7 +99,6 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct exynos_dp_device *dp = to_dp(plat_data);
|
||||
- struct drm_encoder *encoder = &dp->encoder;
|
||||
int ret;
|
||||
|
||||
drm_connector_register(connector);
|
||||
@@ -107,9 +106,7 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
|
||||
|
||||
/* Pre-empt DP connector creation if there's a bridge */
|
||||
if (dp->ptn_bridge) {
|
||||
- bridge->next = dp->ptn_bridge;
|
||||
- dp->ptn_bridge->encoder = encoder;
|
||||
- ret = drm_bridge_attach(encoder->dev, dp->ptn_bridge);
|
||||
+ ret = drm_bridge_attach(&dp->encoder, dp->ptn_bridge, bridge);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to attach bridge to drm\n");
|
||||
bridge->next = NULL;
|
||||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
|
||||
index e07cb1f..812e2ec 100644
|
||||
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
|
||||
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
|
||||
@@ -1718,10 +1718,8 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,
|
||||
}
|
||||
|
||||
bridge = of_drm_find_bridge(dsi->bridge_node);
|
||||
- if (bridge) {
|
||||
- encoder->bridge = bridge;
|
||||
- drm_bridge_attach(drm_dev, bridge);
|
||||
- }
|
||||
+ if (bridge)
|
||||
+ drm_bridge_attach(encoder, bridge, NULL);
|
||||
|
||||
return mipi_dsi_host_register(&dsi->dsi_host);
|
||||
}
|
||||
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
|
||||
index 05a8ee1..c365145 100644
|
||||
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
|
||||
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
|
||||
@@ -160,10 +160,7 @@ static int fsl_dcu_attach_endpoint(struct fsl_dcu_drm_device *fsl_dev,
|
||||
if (!bridge)
|
||||
return -ENODEV;
|
||||
|
||||
- fsl_dev->encoder.bridge = bridge;
|
||||
- bridge->encoder = &fsl_dev->encoder;
|
||||
-
|
||||
- return drm_bridge_attach(fsl_dev->drm, bridge);
|
||||
+ return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL);
|
||||
}
|
||||
|
||||
int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev)
|
||||
diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
|
||||
index 998452a..1737e98 100644
|
||||
--- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
|
||||
+++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
|
||||
@@ -709,10 +709,7 @@ static int dsi_bridge_init(struct drm_device *dev, struct dw_dsi *dsi)
|
||||
int ret;
|
||||
|
||||
/* associate the bridge to dsi encoder */
|
||||
- encoder->bridge = bridge;
|
||||
- bridge->encoder = encoder;
|
||||
-
|
||||
- ret = drm_bridge_attach(dev, bridge);
|
||||
+ ret = drm_bridge_attach(encoder, bridge, NULL);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to attach external bridge\n");
|
||||
return ret;
|
||||
diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
|
||||
index 516d064..ec49ea3 100644
|
||||
--- a/drivers/gpu/drm/imx/imx-ldb.c
|
||||
+++ b/drivers/gpu/drm/imx/imx-ldb.c
|
||||
@@ -454,10 +454,8 @@ static int imx_ldb_register(struct drm_device *drm,
|
||||
DRM_MODE_ENCODER_LVDS, NULL);
|
||||
|
||||
if (imx_ldb_ch->bridge) {
|
||||
- imx_ldb_ch->bridge->encoder = encoder;
|
||||
-
|
||||
- imx_ldb_ch->encoder.bridge = imx_ldb_ch->bridge;
|
||||
- ret = drm_bridge_attach(drm, imx_ldb_ch->bridge);
|
||||
+ ret = drm_bridge_attach(&imx_ldb_ch->encoder,
|
||||
+ imx_ldb_ch->bridge, NULL);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to initialize bridge with drm\n");
|
||||
return ret;
|
||||
diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
|
||||
index 8582a83..51d9f73 100644
|
||||
--- a/drivers/gpu/drm/imx/parallel-display.c
|
||||
+++ b/drivers/gpu/drm/imx/parallel-display.c
|
||||
@@ -191,9 +191,7 @@ static int imx_pd_register(struct drm_device *drm,
|
||||
drm_panel_attach(imxpd->panel, &imxpd->connector);
|
||||
|
||||
if (imxpd->bridge) {
|
||||
- imxpd->bridge->encoder = encoder;
|
||||
- encoder->bridge = imxpd->bridge;
|
||||
- ret = drm_bridge_attach(drm, imxpd->bridge);
|
||||
+ ret = drm_bridge_attach(encoder, imxpd->bridge, NULL);
|
||||
if (ret < 0) {
|
||||
dev_err(imxpd->dev, "failed to attach bridge: %d\n",
|
||||
ret);
|
||||
diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
|
||||
index 90fb831..3bd3bd6 100644
|
||||
--- a/drivers/gpu/drm/mediatek/mtk_dpi.c
|
||||
+++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
|
||||
@@ -63,6 +63,7 @@ enum mtk_dpi_out_color_format {
|
||||
struct mtk_dpi {
|
||||
struct mtk_ddp_comp ddp_comp;
|
||||
struct drm_encoder encoder;
|
||||
+ struct drm_bridge *bridge;
|
||||
void __iomem *regs;
|
||||
struct device *dev;
|
||||
struct clk *engine_clk;
|
||||
@@ -620,8 +621,7 @@ static int mtk_dpi_bind(struct device *dev, struct device *master, void *data)
|
||||
/* Currently DPI0 is fixed to be driven by OVL1 */
|
||||
dpi->encoder.possible_crtcs = BIT(1);
|
||||
|
||||
- dpi->encoder.bridge->encoder = &dpi->encoder;
|
||||
- ret = drm_bridge_attach(dpi->encoder.dev, dpi->encoder.bridge);
|
||||
+ ret = drm_bridge_attach(&dpi->encoder, dpi->bridge, NULL);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to attach bridge: %d\n", ret);
|
||||
goto err_cleanup;
|
||||
@@ -718,9 +718,9 @@ static int mtk_dpi_probe(struct platform_device *pdev)
|
||||
|
||||
dev_info(dev, "Found bridge node: %s\n", bridge_node->full_name);
|
||||
|
||||
- dpi->encoder.bridge = of_drm_find_bridge(bridge_node);
|
||||
+ dpi->bridge = of_drm_find_bridge(bridge_node);
|
||||
of_node_put(bridge_node);
|
||||
- if (!dpi->encoder.bridge)
|
||||
+ if (!dpi->bridge)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DPI);
|
||||
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
|
||||
index 2c42f90..dd71cbb 100644
|
||||
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
|
||||
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
|
||||
@@ -622,26 +622,6 @@ static int mtk_dsi_connector_get_modes(struct drm_connector *connector)
|
||||
.get_modes = mtk_dsi_connector_get_modes,
|
||||
};
|
||||
|
||||
-static int mtk_drm_attach_bridge(struct drm_bridge *bridge,
|
||||
- struct drm_encoder *encoder)
|
||||
-{
|
||||
- int ret;
|
||||
-
|
||||
- if (!bridge)
|
||||
- return -ENOENT;
|
||||
-
|
||||
- encoder->bridge = bridge;
|
||||
- bridge->encoder = encoder;
|
||||
- ret = drm_bridge_attach(encoder->dev, bridge);
|
||||
- if (ret) {
|
||||
- DRM_ERROR("Failed to attach bridge to drm\n");
|
||||
- encoder->bridge = NULL;
|
||||
- bridge->encoder = NULL;
|
||||
- }
|
||||
-
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
static int mtk_dsi_create_connector(struct drm_device *drm, struct mtk_dsi *dsi)
|
||||
{
|
||||
int ret;
|
||||
@@ -692,8 +672,10 @@ static int mtk_dsi_create_conn_enc(struct drm_device *drm, struct mtk_dsi *dsi)
|
||||
dsi->encoder.possible_crtcs = 1;
|
||||
|
||||
/* If there's a bridge, attach to it and let it create the connector */
|
||||
- ret = mtk_drm_attach_bridge(dsi->bridge, &dsi->encoder);
|
||||
+ ret = drm_bridge_attach(&dsi->encoder, dsi->bridge, NULL);
|
||||
if (ret) {
|
||||
+ DRM_ERROR("Failed to attach bridge to drm\n");
|
||||
+
|
||||
/* Otherwise create our own connector and attach to a panel */
|
||||
ret = mtk_dsi_create_connector(drm, dsi);
|
||||
if (ret)
|
||||
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
|
||||
index 0e8c4d9..c262512 100644
|
||||
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
|
||||
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
|
||||
@@ -149,6 +149,7 @@ struct hdmi_audio_param {
|
||||
|
||||
struct mtk_hdmi {
|
||||
struct drm_bridge bridge;
|
||||
+ struct drm_bridge *next_bridge;
|
||||
struct drm_connector conn;
|
||||
struct device *dev;
|
||||
struct phy *phy;
|
||||
@@ -1314,9 +1315,9 @@ static int mtk_hdmi_bridge_attach(struct drm_bridge *bridge)
|
||||
return ret;
|
||||
}
|
||||
|
||||
- if (bridge->next) {
|
||||
- bridge->next->encoder = bridge->encoder;
|
||||
- ret = drm_bridge_attach(bridge->encoder->dev, bridge->next);
|
||||
+ if (hdmi->next_bridge) {
|
||||
+ ret = drm_bridge_attach(bridge->encoder, hdmi->next_bridge,
|
||||
+ bridge);
|
||||
if (ret) {
|
||||
dev_err(hdmi->dev,
|
||||
"Failed to attach external bridge: %d\n", ret);
|
||||
@@ -1510,8 +1511,8 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi,
|
||||
of_node_put(ep);
|
||||
|
||||
if (!of_device_is_compatible(remote, "hdmi-connector")) {
|
||||
- hdmi->bridge.next = of_drm_find_bridge(remote);
|
||||
- if (!hdmi->bridge.next) {
|
||||
+ hdmi->next_bridge = of_drm_find_bridge(remote);
|
||||
+ if (!hdmi->next_bridge) {
|
||||
dev_err(dev, "Waiting for external bridge\n");
|
||||
of_node_put(remote);
|
||||
return -EPROBE_DEFER;
|
||||
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
|
||||
index c8d1f19..2bd8dad 100644
|
||||
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
|
||||
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
|
||||
@@ -579,6 +579,7 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
|
||||
struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
|
||||
struct drm_bridge *bridge = NULL;
|
||||
struct dsi_bridge *dsi_bridge;
|
||||
+ struct drm_encoder *encoder;
|
||||
int ret;
|
||||
|
||||
dsi_bridge = devm_kzalloc(msm_dsi->dev->dev,
|
||||
@@ -590,10 +591,18 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
|
||||
|
||||
dsi_bridge->id = id;
|
||||
|
||||
+ /*
|
||||
+ * HACK: we may not know the external DSI bridge device's mode
|
||||
+ * flags here. We'll get to know them only when the device
|
||||
+ * attaches to the dsi host. For now, assume the bridge supports
|
||||
+ * DSI video mode
|
||||
+ */
|
||||
+ encoder = msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID];
|
||||
+
|
||||
bridge = &dsi_bridge->base;
|
||||
bridge->funcs = &dsi_mgr_bridge_funcs;
|
||||
|
||||
- ret = drm_bridge_attach(msm_dsi->dev, bridge);
|
||||
+ ret = drm_bridge_attach(encoder, bridge, NULL);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
@@ -628,11 +637,7 @@ struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id)
|
||||
encoder = msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID];
|
||||
|
||||
/* link the internal dsi bridge to the external bridge */
|
||||
- int_bridge->next = ext_bridge;
|
||||
- /* set the external bridge's encoder as dsi's encoder */
|
||||
- ext_bridge->encoder = encoder;
|
||||
-
|
||||
- drm_bridge_attach(dev, ext_bridge);
|
||||
+ drm_bridge_attach(encoder, ext_bridge, int_bridge);
|
||||
|
||||
/*
|
||||
* we need the drm_connector created by the external bridge
|
||||
diff --git a/drivers/gpu/drm/msm/edp/edp_bridge.c b/drivers/gpu/drm/msm/edp/edp_bridge.c
|
||||
index 2bc73f82..931a5c9 100644
|
||||
--- a/drivers/gpu/drm/msm/edp/edp_bridge.c
|
||||
+++ b/drivers/gpu/drm/msm/edp/edp_bridge.c
|
||||
@@ -106,7 +106,7 @@ struct drm_bridge *msm_edp_bridge_init(struct msm_edp *edp)
|
||||
bridge = &edp_bridge->base;
|
||||
bridge->funcs = &edp_bridge_funcs;
|
||||
|
||||
- ret = drm_bridge_attach(edp->dev, bridge);
|
||||
+ ret = drm_bridge_attach(edp->encoder, bridge, NULL);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
|
||||
index bacbd5d..4e6d1bf 100644
|
||||
--- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
|
||||
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
|
||||
@@ -227,7 +227,7 @@ struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi)
|
||||
bridge = &hdmi_bridge->base;
|
||||
bridge->funcs = &msm_hdmi_bridge_funcs;
|
||||
|
||||
- ret = drm_bridge_attach(hdmi->dev, bridge);
|
||||
+ ret = drm_bridge_attach(hdmi->encoder, bridge, NULL);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
|
||||
index f9515f5..c4c5d1ab 100644
|
||||
--- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
|
||||
+++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
|
||||
@@ -124,10 +124,7 @@ int rcar_du_hdmienc_init(struct rcar_du_device *rcdu,
|
||||
hdmienc->renc = renc;
|
||||
|
||||
/* Link the bridge to the encoder. */
|
||||
- bridge->encoder = encoder;
|
||||
- encoder->bridge = bridge;
|
||||
-
|
||||
- ret = drm_bridge_attach(rcdu->ddev, bridge);
|
||||
+ ret = drm_bridge_attach(encoder, bridge, NULL);
|
||||
if (ret) {
|
||||
drm_encoder_cleanup(encoder);
|
||||
return ret;
|
||||
diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
|
||||
index e8c1ed0..411dc6e 100644
|
||||
--- a/drivers/gpu/drm/sti/sti_dvo.c
|
||||
+++ b/drivers/gpu/drm/sti/sti_dvo.c
|
||||
@@ -478,14 +478,13 @@ static int sti_dvo_bind(struct device *dev, struct device *master, void *data)
|
||||
return err;
|
||||
}
|
||||
|
||||
- err = drm_bridge_attach(drm_dev, bridge);
|
||||
+ err = drm_bridge_attach(encoder, bridge, NULL);
|
||||
if (err) {
|
||||
DRM_ERROR("Failed to attach bridge\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
dvo->bridge = bridge;
|
||||
- encoder->bridge = bridge;
|
||||
connector->encoder = encoder;
|
||||
dvo->encoder = encoder;
|
||||
|
||||
diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c
|
||||
index 96f336d..66d37d78 100644
|
||||
--- a/drivers/gpu/drm/sti/sti_hda.c
|
||||
+++ b/drivers/gpu/drm/sti/sti_hda.c
|
||||
@@ -707,9 +707,8 @@ static int sti_hda_bind(struct device *dev, struct device *master, void *data)
|
||||
|
||||
bridge->driver_private = hda;
|
||||
bridge->funcs = &sti_hda_bridge_funcs;
|
||||
- drm_bridge_attach(drm_dev, bridge);
|
||||
+ drm_bridge_attach(encoder, bridge, NULL);
|
||||
|
||||
- encoder->bridge = bridge;
|
||||
connector->encoder = encoder;
|
||||
|
||||
drm_connector = (struct drm_connector *)connector;
|
||||
diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
|
||||
index 376b076..f0af1ae 100644
|
||||
--- a/drivers/gpu/drm/sti/sti_hdmi.c
|
||||
+++ b/drivers/gpu/drm/sti/sti_hdmi.c
|
||||
@@ -1308,9 +1308,8 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)
|
||||
|
||||
bridge->driver_private = hdmi;
|
||||
bridge->funcs = &sti_hdmi_bridge_funcs;
|
||||
- drm_bridge_attach(drm_dev, bridge);
|
||||
+ drm_bridge_attach(encoder, bridge, NULL);
|
||||
|
||||
- encoder->bridge = bridge;
|
||||
connector->encoder = encoder;
|
||||
|
||||
drm_connector = (struct drm_connector *)connector;
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
|
||||
index f5e86fe..757208f 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
|
||||
@@ -208,6 +208,7 @@ int sun4i_rgb_init(struct drm_device *drm)
|
||||
struct sun4i_drv *drv = drm->dev_private;
|
||||
struct sun4i_tcon *tcon = drv->tcon;
|
||||
struct drm_encoder *encoder;
|
||||
+ struct drm_bridge *bridge;
|
||||
struct sun4i_rgb *rgb;
|
||||
int ret;
|
||||
|
||||
@@ -218,8 +219,8 @@ int sun4i_rgb_init(struct drm_device *drm)
|
||||
encoder = &rgb->encoder;
|
||||
|
||||
tcon->panel = sun4i_tcon_find_panel(tcon->dev->of_node);
|
||||
- encoder->bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
|
||||
- if (IS_ERR(tcon->panel) && IS_ERR(encoder->bridge)) {
|
||||
+ bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
|
||||
+ if (IS_ERR(tcon->panel) && IS_ERR(bridge)) {
|
||||
dev_info(drm->dev, "No panel or bridge found... RGB output disabled\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -260,16 +261,12 @@ int sun4i_rgb_init(struct drm_device *drm)
|
||||
}
|
||||
}
|
||||
|
||||
- if (!IS_ERR(encoder->bridge)) {
|
||||
- encoder->bridge->encoder = &rgb->encoder;
|
||||
-
|
||||
- ret = drm_bridge_attach(drm, encoder->bridge);
|
||||
+ if (!IS_ERR(bridge)) {
|
||||
+ ret = drm_bridge_attach(encoder, bridge, NULL);
|
||||
if (ret) {
|
||||
dev_err(drm->dev, "Couldn't attach our bridge\n");
|
||||
goto err_cleanup_connector;
|
||||
}
|
||||
- } else {
|
||||
- encoder->bridge = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_external.c b/drivers/gpu/drm/tilcdc/tilcdc_external.c
|
||||
index c67d7cd..b0dd5e8 100644
|
||||
--- a/drivers/gpu/drm/tilcdc/tilcdc_external.c
|
||||
+++ b/drivers/gpu/drm/tilcdc/tilcdc_external.c
|
||||
@@ -167,10 +167,8 @@ int tilcdc_attach_bridge(struct drm_device *ddev, struct drm_bridge *bridge)
|
||||
int ret;
|
||||
|
||||
priv->external_encoder->possible_crtcs = BIT(0);
|
||||
- priv->external_encoder->bridge = bridge;
|
||||
- bridge->encoder = priv->external_encoder;
|
||||
|
||||
- ret = drm_bridge_attach(ddev, bridge);
|
||||
+ ret = drm_bridge_attach(priv->external_encoder, bridge, NULL);
|
||||
if (ret) {
|
||||
dev_err(ddev->dev, "drm_bridge_attach() failed %d\n", ret);
|
||||
return ret;
|
||||
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
|
||||
index 530a1d6..94e5ee9 100644
|
||||
--- a/include/drm/drm_bridge.h
|
||||
+++ b/include/drm/drm_bridge.h
|
||||
@@ -201,7 +201,8 @@ struct drm_bridge {
|
||||
int drm_bridge_add(struct drm_bridge *bridge);
|
||||
void drm_bridge_remove(struct drm_bridge *bridge);
|
||||
struct drm_bridge *of_drm_find_bridge(struct device_node *np);
|
||||
-int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge);
|
||||
+int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
|
||||
+ struct drm_bridge *previous);
|
||||
void drm_bridge_detach(struct drm_bridge *bridge);
|
||||
|
||||
bool drm_bridge_mode_fixup(struct drm_bridge *bridge,
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
From 4d69de06ed2934b45c0e6b2a5056ef2a7caa0b9a Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:28:51 +0200
|
||||
Subject: [PATCH 11/93] drm: bridge: dw-hdmi: Merge __hdmi_phy_i2c_write and
|
||||
hdmi_phy_i2c_write
|
||||
|
||||
The latter is just an int wrapper around the former void function that
|
||||
unconditionally returns 0. As the return value is never checked, merge
|
||||
the two functions into one.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-2-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 9 +--------
|
||||
1 file changed, 1 insertion(+), 8 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index f5009ae..a668550 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -868,7 +868,7 @@ static bool hdmi_phy_wait_i2c_done(struct dw_hdmi *hdmi, int msec)
|
||||
return true;
|
||||
}
|
||||
|
||||
-static void __hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
|
||||
+static void hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
|
||||
unsigned char addr)
|
||||
{
|
||||
hdmi_writeb(hdmi, 0xFF, HDMI_IH_I2CMPHY_STAT0);
|
||||
@@ -882,13 +882,6 @@ static void __hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
|
||||
hdmi_phy_wait_i2c_done(hdmi, 1000);
|
||||
}
|
||||
|
||||
-static int hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
|
||||
- unsigned char addr)
|
||||
-{
|
||||
- __hdmi_phy_i2c_write(hdmi, data, addr);
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
static void dw_hdmi_phy_enable_powerdown(struct dw_hdmi *hdmi, bool enable)
|
||||
{
|
||||
hdmi_mask_writeb(hdmi, !enable, HDMI_PHY_CONF0,
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
From fefa6576d7b085c7712fdc2b5af10e61f3fa1841 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:28:52 +0200
|
||||
Subject: [PATCH 12/93] drm: bridge: dw-hdmi: Remove unneeded arguments to
|
||||
bind/unbind functions
|
||||
|
||||
The master argument isn't used. The data argument, a void pointer, is
|
||||
used by the bind function only where it's cast to a drm_device pointer,
|
||||
which can easily be obtained from the encoder argument instead. Remove
|
||||
them.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-3-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 8 +++-----
|
||||
drivers/gpu/drm/imx/dw_hdmi-imx.c | 4 ++--
|
||||
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 4 ++--
|
||||
include/drm/bridge/dw_hdmi.h | 5 ++---
|
||||
4 files changed, 9 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index a668550..f868946 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -1854,12 +1854,10 @@ static int dw_hdmi_register(struct drm_device *drm, struct dw_hdmi *hdmi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-int dw_hdmi_bind(struct device *dev, struct device *master,
|
||||
- void *data, struct drm_encoder *encoder,
|
||||
+int dw_hdmi_bind(struct device *dev, struct drm_encoder *encoder,
|
||||
struct resource *iores, int irq,
|
||||
const struct dw_hdmi_plat_data *plat_data)
|
||||
{
|
||||
- struct drm_device *drm = data;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct platform_device_info pdevinfo;
|
||||
struct device_node *ddc_node;
|
||||
@@ -1992,7 +1990,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
|
||||
if (ret)
|
||||
goto err_iahb;
|
||||
|
||||
- ret = dw_hdmi_register(drm, hdmi);
|
||||
+ ret = dw_hdmi_register(encoder->dev, hdmi);
|
||||
if (ret)
|
||||
goto err_iahb;
|
||||
|
||||
@@ -2059,7 +2057,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dw_hdmi_bind);
|
||||
|
||||
-void dw_hdmi_unbind(struct device *dev, struct device *master, void *data)
|
||||
+void dw_hdmi_unbind(struct device *dev)
|
||||
{
|
||||
struct dw_hdmi *hdmi = dev_get_drvdata(dev);
|
||||
|
||||
diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c
|
||||
index 359cd27..f796658 100644
|
||||
--- a/drivers/gpu/drm/imx/dw_hdmi-imx.c
|
||||
+++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c
|
||||
@@ -249,7 +249,7 @@ static int dw_hdmi_imx_bind(struct device *dev, struct device *master,
|
||||
drm_encoder_init(drm, encoder, &dw_hdmi_imx_encoder_funcs,
|
||||
DRM_MODE_ENCODER_TMDS, NULL);
|
||||
|
||||
- ret = dw_hdmi_bind(dev, master, data, encoder, iores, irq, plat_data);
|
||||
+ ret = dw_hdmi_bind(dev, encoder, iores, irq, plat_data);
|
||||
|
||||
/*
|
||||
* If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(),
|
||||
@@ -264,7 +264,7 @@ static int dw_hdmi_imx_bind(struct device *dev, struct device *master,
|
||||
static void dw_hdmi_imx_unbind(struct device *dev, struct device *master,
|
||||
void *data)
|
||||
{
|
||||
- return dw_hdmi_unbind(dev, master, data);
|
||||
+ return dw_hdmi_unbind(dev);
|
||||
}
|
||||
|
||||
static const struct component_ops dw_hdmi_imx_ops = {
|
||||
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
|
||||
index 0665fb9..e8fb5c5 100644
|
||||
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
|
||||
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
|
||||
@@ -301,7 +301,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
|
||||
drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs,
|
||||
DRM_MODE_ENCODER_TMDS, NULL);
|
||||
|
||||
- ret = dw_hdmi_bind(dev, master, data, encoder, iores, irq, plat_data);
|
||||
+ ret = dw_hdmi_bind(dev, encoder, iores, irq, plat_data);
|
||||
|
||||
/*
|
||||
* If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(),
|
||||
@@ -316,7 +316,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
|
||||
static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master,
|
||||
void *data)
|
||||
{
|
||||
- return dw_hdmi_unbind(dev, master, data);
|
||||
+ return dw_hdmi_unbind(dev);
|
||||
}
|
||||
|
||||
static const struct component_ops dw_hdmi_rockchip_ops = {
|
||||
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
|
||||
index bae79f3..11edda6 100644
|
||||
--- a/include/drm/bridge/dw_hdmi.h
|
||||
+++ b/include/drm/bridge/dw_hdmi.h
|
||||
@@ -56,9 +56,8 @@ struct dw_hdmi_plat_data {
|
||||
struct drm_display_mode *mode);
|
||||
};
|
||||
|
||||
-void dw_hdmi_unbind(struct device *dev, struct device *master, void *data);
|
||||
-int dw_hdmi_bind(struct device *dev, struct device *master,
|
||||
- void *data, struct drm_encoder *encoder,
|
||||
+void dw_hdmi_unbind(struct device *dev);
|
||||
+int dw_hdmi_bind(struct device *dev, struct drm_encoder *encoder,
|
||||
struct resource *iores, int irq,
|
||||
const struct dw_hdmi_plat_data *plat_data);
|
||||
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
From 4c8725b2de2a5b87850fb7cfa9d2ecf4499e05fb Mon Sep 17 00:00:00 2001
|
||||
From: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:28:53 +0200
|
||||
Subject: [PATCH 13/93] drm: bridge: dw-hdmi: Remove unused function parameter
|
||||
|
||||
The 'prep' parameter passed to hdmi_phy_configure() is useless. It is
|
||||
hardcoded as 0, and if set, simply prevents the configure function from
|
||||
executing.
|
||||
|
||||
Remove it.
|
||||
|
||||
Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-4-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 7 ++-----
|
||||
1 file changed, 2 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index f868946..5f8044a 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -931,7 +931,7 @@ static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable)
|
||||
HDMI_PHY_CONF0_SELDIPIF_MASK);
|
||||
}
|
||||
|
||||
-static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep,
|
||||
+static int hdmi_phy_configure(struct dw_hdmi *hdmi,
|
||||
unsigned char res, int cscon)
|
||||
{
|
||||
unsigned res_idx;
|
||||
@@ -941,9 +941,6 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep,
|
||||
const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
|
||||
const struct dw_hdmi_phy_config *phy_config = pdata->phy_config;
|
||||
|
||||
- if (prep)
|
||||
- return -EINVAL;
|
||||
-
|
||||
switch (res) {
|
||||
case 0: /* color resolution 0 is 8 bit colour depth */
|
||||
case 8:
|
||||
@@ -1072,7 +1069,7 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
|
||||
dw_hdmi_phy_enable_powerdown(hdmi, true);
|
||||
|
||||
/* Enable CSC */
|
||||
- ret = hdmi_phy_configure(hdmi, 0, 8, cscon);
|
||||
+ ret = hdmi_phy_configure(hdmi, 8, cscon);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
From 891854dbb712fe784cc0553c05bd05a8734d6a3e Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:28:54 +0200
|
||||
Subject: [PATCH 14/93] drm: bridge: dw-hdmi: Embed drm_bridge in struct
|
||||
dw_hdmi
|
||||
|
||||
The drm_bridge instance is always needed, there's no point in allocating
|
||||
it separately.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-5-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 13 +++----------
|
||||
1 file changed, 3 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 5f8044a..2c85b6c 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -116,7 +116,7 @@ struct dw_hdmi_i2c {
|
||||
struct dw_hdmi {
|
||||
struct drm_connector connector;
|
||||
struct drm_encoder *encoder;
|
||||
- struct drm_bridge *bridge;
|
||||
+ struct drm_bridge bridge;
|
||||
|
||||
struct platform_device *audio;
|
||||
enum dw_hdmi_devtype dev_type;
|
||||
@@ -1806,7 +1806,7 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
if (intr_stat & HDMI_IH_PHY_STAT0_HPD) {
|
||||
dev_dbg(hdmi->dev, "EVENT=%s\n",
|
||||
phy_int_pol & HDMI_PHY_HPD ? "plugin" : "plugout");
|
||||
- drm_helper_hpd_irq_event(hdmi->bridge->dev);
|
||||
+ drm_helper_hpd_irq_event(hdmi->bridge.dev);
|
||||
}
|
||||
|
||||
hdmi_writeb(hdmi, intr_stat, HDMI_IH_PHY_STAT0);
|
||||
@@ -1819,16 +1819,9 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
static int dw_hdmi_register(struct drm_device *drm, struct dw_hdmi *hdmi)
|
||||
{
|
||||
struct drm_encoder *encoder = hdmi->encoder;
|
||||
- struct drm_bridge *bridge;
|
||||
+ struct drm_bridge *bridge = &hdmi->bridge;
|
||||
int ret;
|
||||
|
||||
- bridge = devm_kzalloc(drm->dev, sizeof(*bridge), GFP_KERNEL);
|
||||
- if (!bridge) {
|
||||
- DRM_ERROR("Failed to allocate drm bridge\n");
|
||||
- return -ENOMEM;
|
||||
- }
|
||||
-
|
||||
- hdmi->bridge = bridge;
|
||||
bridge->driver_private = hdmi;
|
||||
bridge->funcs = &dw_hdmi_bridge_funcs;
|
||||
ret = drm_bridge_attach(encoder, bridge, NULL);
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
From 9fef18b9a29bb46c33bd724b1f66296b69fa65df Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:28:55 +0200
|
||||
Subject: [PATCH 15/93] drm: bridge: dw-hdmi: Remove encoder field from struct
|
||||
dw_hdmi
|
||||
|
||||
The field isn't needed, remove it.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-6-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 9 +++------
|
||||
1 file changed, 3 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 2c85b6c..ef10bb8 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -115,7 +115,6 @@ struct dw_hdmi_i2c {
|
||||
|
||||
struct dw_hdmi {
|
||||
struct drm_connector connector;
|
||||
- struct drm_encoder *encoder;
|
||||
struct drm_bridge bridge;
|
||||
|
||||
struct platform_device *audio;
|
||||
@@ -1816,9 +1815,8 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
-static int dw_hdmi_register(struct drm_device *drm, struct dw_hdmi *hdmi)
|
||||
+static int dw_hdmi_register(struct drm_encoder *encoder, struct dw_hdmi *hdmi)
|
||||
{
|
||||
- struct drm_encoder *encoder = hdmi->encoder;
|
||||
struct drm_bridge *bridge = &hdmi->bridge;
|
||||
int ret;
|
||||
|
||||
@@ -1835,7 +1833,7 @@ static int dw_hdmi_register(struct drm_device *drm, struct dw_hdmi *hdmi)
|
||||
drm_connector_helper_add(&hdmi->connector,
|
||||
&dw_hdmi_connector_helper_funcs);
|
||||
|
||||
- drm_connector_init(drm, &hdmi->connector,
|
||||
+ drm_connector_init(encoder->dev, &hdmi->connector,
|
||||
&dw_hdmi_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_HDMIA);
|
||||
|
||||
@@ -1867,7 +1865,6 @@ int dw_hdmi_bind(struct device *dev, struct drm_encoder *encoder,
|
||||
hdmi->dev = dev;
|
||||
hdmi->dev_type = plat_data->dev_type;
|
||||
hdmi->sample_rate = 48000;
|
||||
- hdmi->encoder = encoder;
|
||||
hdmi->disabled = true;
|
||||
hdmi->rxsense = true;
|
||||
hdmi->phy_mask = (u8)~(HDMI_PHY_HPD | HDMI_PHY_RX_SENSE);
|
||||
@@ -1980,7 +1977,7 @@ int dw_hdmi_bind(struct device *dev, struct drm_encoder *encoder,
|
||||
if (ret)
|
||||
goto err_iahb;
|
||||
|
||||
- ret = dw_hdmi_register(encoder->dev, hdmi);
|
||||
+ ret = dw_hdmi_register(encoder, hdmi);
|
||||
if (ret)
|
||||
goto err_iahb;
|
||||
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
From 259254dabd150067bf932e192dd9ed8b3d545755 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:28:56 +0200
|
||||
Subject: [PATCH 16/93] drm: bridge: dw-hdmi: Don't forward HPD events to DRM
|
||||
core before attach
|
||||
|
||||
Hotplug events should only be forwarded to the DRM core by the interrupt
|
||||
handler when the bridge has been attached, otherwise the DRM device
|
||||
pointer will be NULL, resulting in a crash.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-7-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index ef10bb8..488dc1a 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -1805,7 +1805,8 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
if (intr_stat & HDMI_IH_PHY_STAT0_HPD) {
|
||||
dev_dbg(hdmi->dev, "EVENT=%s\n",
|
||||
phy_int_pol & HDMI_PHY_HPD ? "plugin" : "plugout");
|
||||
- drm_helper_hpd_irq_event(hdmi->bridge.dev);
|
||||
+ if (hdmi->bridge.dev)
|
||||
+ drm_helper_hpd_irq_event(hdmi->bridge.dev);
|
||||
}
|
||||
|
||||
hdmi_writeb(hdmi, intr_stat, HDMI_IH_PHY_STAT0);
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
From 1de2e27b041a944da876ec10a530991d82dfd991 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:28:57 +0200
|
||||
Subject: [PATCH 17/93] drm: bridge: dw-hdmi: Move IRQ and IO resource
|
||||
allocation to common code
|
||||
|
||||
There's no need to duplicate identical code in multiple drivers (two at
|
||||
the moment, one more to come soon). Move it to the dw-hdmi core where it
|
||||
can be shared. If resource allocation ever becomes device-specific later
|
||||
we'll always have the option of splitting it out again.
|
||||
|
||||
While it at pass the platform device to the bind function to avoid
|
||||
having to cast struct device to struct platform_device.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-8-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 13 ++++++++++---
|
||||
drivers/gpu/drm/imx/dw_hdmi-imx.c | 12 +-----------
|
||||
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 12 +-----------
|
||||
include/drm/bridge/dw_hdmi.h | 3 +--
|
||||
4 files changed, 13 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 488dc1a..563cbec 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -1843,14 +1843,16 @@ static int dw_hdmi_register(struct drm_encoder *encoder, struct dw_hdmi *hdmi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-int dw_hdmi_bind(struct device *dev, struct drm_encoder *encoder,
|
||||
- struct resource *iores, int irq,
|
||||
+int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
|
||||
const struct dw_hdmi_plat_data *plat_data)
|
||||
{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct platform_device_info pdevinfo;
|
||||
struct device_node *ddc_node;
|
||||
struct dw_hdmi *hdmi;
|
||||
+ struct resource *iores;
|
||||
+ int irq;
|
||||
int ret;
|
||||
u32 val = 1;
|
||||
u8 config0;
|
||||
@@ -1903,6 +1905,7 @@ int dw_hdmi_bind(struct device *dev, struct drm_encoder *encoder,
|
||||
dev_dbg(hdmi->dev, "no ddc property found\n");
|
||||
}
|
||||
|
||||
+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
hdmi->regs = devm_ioremap_resource(dev, iores);
|
||||
if (IS_ERR(hdmi->regs)) {
|
||||
ret = PTR_ERR(hdmi->regs);
|
||||
@@ -1945,6 +1948,10 @@ int dw_hdmi_bind(struct device *dev, struct drm_encoder *encoder,
|
||||
|
||||
initialize_hdmi_ih_mutes(hdmi);
|
||||
|
||||
+ irq = platform_get_irq(pdev, 0);
|
||||
+ if (irq < 0)
|
||||
+ goto err_iahb;
|
||||
+
|
||||
ret = devm_request_threaded_irq(dev, irq, dw_hdmi_hardirq,
|
||||
dw_hdmi_irq, IRQF_SHARED,
|
||||
dev_name(dev), hdmi);
|
||||
@@ -2025,7 +2032,7 @@ int dw_hdmi_bind(struct device *dev, struct drm_encoder *encoder,
|
||||
if (hdmi->i2c)
|
||||
dw_hdmi_i2c_init(hdmi);
|
||||
|
||||
- dev_set_drvdata(dev, hdmi);
|
||||
+ platform_set_drvdata(pdev, hdmi);
|
||||
|
||||
return 0;
|
||||
|
||||
diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c
|
||||
index f796658..f645275 100644
|
||||
--- a/drivers/gpu/drm/imx/dw_hdmi-imx.c
|
||||
+++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c
|
||||
@@ -207,8 +207,6 @@ static int dw_hdmi_imx_bind(struct device *dev, struct device *master,
|
||||
struct drm_device *drm = data;
|
||||
struct drm_encoder *encoder;
|
||||
struct imx_hdmi *hdmi;
|
||||
- struct resource *iores;
|
||||
- int irq;
|
||||
int ret;
|
||||
|
||||
if (!pdev->dev.of_node)
|
||||
@@ -223,14 +221,6 @@ static int dw_hdmi_imx_bind(struct device *dev, struct device *master,
|
||||
hdmi->dev = &pdev->dev;
|
||||
encoder = &hdmi->encoder;
|
||||
|
||||
- irq = platform_get_irq(pdev, 0);
|
||||
- if (irq < 0)
|
||||
- return irq;
|
||||
-
|
||||
- iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
- if (!iores)
|
||||
- return -ENXIO;
|
||||
-
|
||||
encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
|
||||
/*
|
||||
* If we failed to find the CRTC(s) which this encoder is
|
||||
@@ -249,7 +239,7 @@ static int dw_hdmi_imx_bind(struct device *dev, struct device *master,
|
||||
drm_encoder_init(drm, encoder, &dw_hdmi_imx_encoder_funcs,
|
||||
DRM_MODE_ENCODER_TMDS, NULL);
|
||||
|
||||
- ret = dw_hdmi_bind(dev, encoder, iores, irq, plat_data);
|
||||
+ ret = dw_hdmi_bind(pdev, encoder, plat_data);
|
||||
|
||||
/*
|
||||
* If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(),
|
||||
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
|
||||
index e8fb5c5..a6d4a02 100644
|
||||
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
|
||||
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
|
||||
@@ -257,8 +257,6 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
|
||||
struct drm_device *drm = data;
|
||||
struct drm_encoder *encoder;
|
||||
struct rockchip_hdmi *hdmi;
|
||||
- struct resource *iores;
|
||||
- int irq;
|
||||
int ret;
|
||||
|
||||
if (!pdev->dev.of_node)
|
||||
@@ -273,14 +271,6 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
|
||||
hdmi->dev = &pdev->dev;
|
||||
encoder = &hdmi->encoder;
|
||||
|
||||
- irq = platform_get_irq(pdev, 0);
|
||||
- if (irq < 0)
|
||||
- return irq;
|
||||
-
|
||||
- iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
- if (!iores)
|
||||
- return -ENXIO;
|
||||
-
|
||||
encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
|
||||
/*
|
||||
* If we failed to find the CRTC(s) which this encoder is
|
||||
@@ -301,7 +291,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
|
||||
drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs,
|
||||
DRM_MODE_ENCODER_TMDS, NULL);
|
||||
|
||||
- ret = dw_hdmi_bind(dev, encoder, iores, irq, plat_data);
|
||||
+ ret = dw_hdmi_bind(pdev, encoder, plat_data);
|
||||
|
||||
/*
|
||||
* If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(),
|
||||
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
|
||||
index 11edda6..94ff6ed 100644
|
||||
--- a/include/drm/bridge/dw_hdmi.h
|
||||
+++ b/include/drm/bridge/dw_hdmi.h
|
||||
@@ -57,8 +57,7 @@ struct dw_hdmi_plat_data {
|
||||
};
|
||||
|
||||
void dw_hdmi_unbind(struct device *dev);
|
||||
-int dw_hdmi_bind(struct device *dev, struct drm_encoder *encoder,
|
||||
- struct resource *iores, int irq,
|
||||
+int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
|
||||
const struct dw_hdmi_plat_data *plat_data);
|
||||
|
||||
void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate);
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
From 78e502a47988bfdb298e8416444c0f1f6e7e93a4 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:28:58 +0200
|
||||
Subject: [PATCH 18/93] drm: bridge: dw-hdmi: Reorder functions to prepare for
|
||||
next commit
|
||||
|
||||
The next commit will reference structures and functions in a way that
|
||||
currently requires forward declarations. Reorder the functions to avoid
|
||||
that. No functional change to the code is performed.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-9-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 72 ++++++++++++++++++++--------------------
|
||||
1 file changed, 36 insertions(+), 36 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 563cbec..92ce9e5 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -1575,42 +1575,6 @@ static void dw_hdmi_update_phy_mask(struct dw_hdmi *hdmi)
|
||||
hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0);
|
||||
}
|
||||
|
||||
-static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge,
|
||||
- struct drm_display_mode *orig_mode,
|
||||
- struct drm_display_mode *mode)
|
||||
-{
|
||||
- struct dw_hdmi *hdmi = bridge->driver_private;
|
||||
-
|
||||
- mutex_lock(&hdmi->mutex);
|
||||
-
|
||||
- /* Store the display mode for plugin/DKMS poweron events */
|
||||
- memcpy(&hdmi->previous_mode, mode, sizeof(hdmi->previous_mode));
|
||||
-
|
||||
- mutex_unlock(&hdmi->mutex);
|
||||
-}
|
||||
-
|
||||
-static void dw_hdmi_bridge_disable(struct drm_bridge *bridge)
|
||||
-{
|
||||
- struct dw_hdmi *hdmi = bridge->driver_private;
|
||||
-
|
||||
- mutex_lock(&hdmi->mutex);
|
||||
- hdmi->disabled = true;
|
||||
- dw_hdmi_update_power(hdmi);
|
||||
- dw_hdmi_update_phy_mask(hdmi);
|
||||
- mutex_unlock(&hdmi->mutex);
|
||||
-}
|
||||
-
|
||||
-static void dw_hdmi_bridge_enable(struct drm_bridge *bridge)
|
||||
-{
|
||||
- struct dw_hdmi *hdmi = bridge->driver_private;
|
||||
-
|
||||
- mutex_lock(&hdmi->mutex);
|
||||
- hdmi->disabled = false;
|
||||
- dw_hdmi_update_power(hdmi);
|
||||
- dw_hdmi_update_phy_mask(hdmi);
|
||||
- mutex_unlock(&hdmi->mutex);
|
||||
-}
|
||||
-
|
||||
static enum drm_connector_status
|
||||
dw_hdmi_connector_detect(struct drm_connector *connector, bool force)
|
||||
{
|
||||
@@ -1703,6 +1667,42 @@ static void dw_hdmi_connector_force(struct drm_connector *connector)
|
||||
.best_encoder = drm_atomic_helper_best_encoder,
|
||||
};
|
||||
|
||||
+static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge,
|
||||
+ struct drm_display_mode *orig_mode,
|
||||
+ struct drm_display_mode *mode)
|
||||
+{
|
||||
+ struct dw_hdmi *hdmi = bridge->driver_private;
|
||||
+
|
||||
+ mutex_lock(&hdmi->mutex);
|
||||
+
|
||||
+ /* Store the display mode for plugin/DKMS poweron events */
|
||||
+ memcpy(&hdmi->previous_mode, mode, sizeof(hdmi->previous_mode));
|
||||
+
|
||||
+ mutex_unlock(&hdmi->mutex);
|
||||
+}
|
||||
+
|
||||
+static void dw_hdmi_bridge_disable(struct drm_bridge *bridge)
|
||||
+{
|
||||
+ struct dw_hdmi *hdmi = bridge->driver_private;
|
||||
+
|
||||
+ mutex_lock(&hdmi->mutex);
|
||||
+ hdmi->disabled = true;
|
||||
+ dw_hdmi_update_power(hdmi);
|
||||
+ dw_hdmi_update_phy_mask(hdmi);
|
||||
+ mutex_unlock(&hdmi->mutex);
|
||||
+}
|
||||
+
|
||||
+static void dw_hdmi_bridge_enable(struct drm_bridge *bridge)
|
||||
+{
|
||||
+ struct dw_hdmi *hdmi = bridge->driver_private;
|
||||
+
|
||||
+ mutex_lock(&hdmi->mutex);
|
||||
+ hdmi->disabled = false;
|
||||
+ dw_hdmi_update_power(hdmi);
|
||||
+ dw_hdmi_update_phy_mask(hdmi);
|
||||
+ mutex_unlock(&hdmi->mutex);
|
||||
+}
|
||||
+
|
||||
static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = {
|
||||
.enable = dw_hdmi_bridge_enable,
|
||||
.disable = dw_hdmi_bridge_disable,
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
From 8b9fed5697ca5dad3197822eb34ae317f45a16a5 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:28:59 +0200
|
||||
Subject: [PATCH 19/93] drm: bridge: dw-hdmi: Create connector in the bridge
|
||||
attach operation
|
||||
|
||||
The DRM device is not guaranteed by the bridge API to be available
|
||||
before the attach callback. The driver performs properly at the moment
|
||||
as it doesn't use the drm_bridge_add() registration method. As this will
|
||||
be changed later, move connector creation to attach time to ensure
|
||||
compatibility with the API.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-10-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 33 ++++++++++++++++++++-------------
|
||||
1 file changed, 20 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 92ce9e5..88cd40a 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -1667,6 +1667,25 @@ static void dw_hdmi_connector_force(struct drm_connector *connector)
|
||||
.best_encoder = drm_atomic_helper_best_encoder,
|
||||
};
|
||||
|
||||
+static int dw_hdmi_bridge_attach(struct drm_bridge *bridge)
|
||||
+{
|
||||
+ struct dw_hdmi *hdmi = bridge->driver_private;
|
||||
+ struct drm_encoder *encoder = bridge->encoder;
|
||||
+ struct drm_connector *connector = &hdmi->connector;
|
||||
+
|
||||
+ connector->interlace_allowed = 1;
|
||||
+ connector->polled = DRM_CONNECTOR_POLL_HPD;
|
||||
+
|
||||
+ drm_connector_helper_add(connector, &dw_hdmi_connector_helper_funcs);
|
||||
+
|
||||
+ drm_connector_init(bridge->dev, connector, &dw_hdmi_connector_funcs,
|
||||
+ DRM_MODE_CONNECTOR_HDMIA);
|
||||
+
|
||||
+ drm_mode_connector_attach_encoder(connector, encoder);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge,
|
||||
struct drm_display_mode *orig_mode,
|
||||
struct drm_display_mode *mode)
|
||||
@@ -1704,6 +1723,7 @@ static void dw_hdmi_bridge_enable(struct drm_bridge *bridge)
|
||||
}
|
||||
|
||||
static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = {
|
||||
+ .attach = dw_hdmi_bridge_attach,
|
||||
.enable = dw_hdmi_bridge_enable,
|
||||
.disable = dw_hdmi_bridge_disable,
|
||||
.mode_set = dw_hdmi_bridge_mode_set,
|
||||
@@ -1829,17 +1849,6 @@ static int dw_hdmi_register(struct drm_encoder *encoder, struct dw_hdmi *hdmi)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
|
||||
-
|
||||
- drm_connector_helper_add(&hdmi->connector,
|
||||
- &dw_hdmi_connector_helper_funcs);
|
||||
-
|
||||
- drm_connector_init(encoder->dev, &hdmi->connector,
|
||||
- &dw_hdmi_connector_funcs,
|
||||
- DRM_MODE_CONNECTOR_HDMIA);
|
||||
-
|
||||
- drm_mode_connector_attach_encoder(&hdmi->connector, encoder);
|
||||
-
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1862,8 +1871,6 @@ int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
|
||||
if (!hdmi)
|
||||
return -ENOMEM;
|
||||
|
||||
- hdmi->connector.interlace_allowed = 1;
|
||||
-
|
||||
hdmi->plat_data = plat_data;
|
||||
hdmi->dev = dev;
|
||||
hdmi->dev_type = plat_data->dev_type;
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,220 @@
|
|||
From 200c0b9edb6b1203d6db6391d940f69b6f56e1d6 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:29:00 +0200
|
||||
Subject: [PATCH 20/93] drm: bridge: dw-hdmi: Implement DRM bridge registration
|
||||
|
||||
As an option for drivers not based on the component framework, register
|
||||
the bridge with the DRM core with the DRM bridge API. Existing drivers
|
||||
based on dw_hdmi_bind() and dw_hdmi_unbind() are not affected as those
|
||||
functions are preserved with their current behaviour.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-11-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 112 ++++++++++++++++++++++++++++-----------
|
||||
include/drm/bridge/dw_hdmi.h | 3 ++
|
||||
2 files changed, 83 insertions(+), 32 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 88cd40a..107fea4 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -1836,24 +1836,9 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
-static int dw_hdmi_register(struct drm_encoder *encoder, struct dw_hdmi *hdmi)
|
||||
-{
|
||||
- struct drm_bridge *bridge = &hdmi->bridge;
|
||||
- int ret;
|
||||
-
|
||||
- bridge->driver_private = hdmi;
|
||||
- bridge->funcs = &dw_hdmi_bridge_funcs;
|
||||
- ret = drm_bridge_attach(encoder, bridge, NULL);
|
||||
- if (ret) {
|
||||
- DRM_ERROR("Failed to initialize bridge with drm\n");
|
||||
- return -EINVAL;
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
|
||||
- const struct dw_hdmi_plat_data *plat_data)
|
||||
+static struct dw_hdmi *
|
||||
+__dw_hdmi_probe(struct platform_device *pdev,
|
||||
+ const struct dw_hdmi_plat_data *plat_data)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
@@ -1869,7 +1854,7 @@ int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
|
||||
|
||||
hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
|
||||
if (!hdmi)
|
||||
- return -ENOMEM;
|
||||
+ return ERR_PTR(-ENOMEM);
|
||||
|
||||
hdmi->plat_data = plat_data;
|
||||
hdmi->dev = dev;
|
||||
@@ -1896,7 +1881,7 @@ int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "reg-io-width must be 1 or 4\n");
|
||||
- return -EINVAL;
|
||||
+ return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
|
||||
@@ -1905,7 +1890,7 @@ int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
|
||||
of_node_put(ddc_node);
|
||||
if (!hdmi->ddc) {
|
||||
dev_dbg(hdmi->dev, "failed to read ddc node\n");
|
||||
- return -EPROBE_DEFER;
|
||||
+ return ERR_PTR(-EPROBE_DEFER);
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -1956,8 +1941,10 @@ int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
|
||||
initialize_hdmi_ih_mutes(hdmi);
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
- if (irq < 0)
|
||||
+ if (irq < 0) {
|
||||
+ ret = irq;
|
||||
goto err_iahb;
|
||||
+ }
|
||||
|
||||
ret = devm_request_threaded_irq(dev, irq, dw_hdmi_hardirq,
|
||||
dw_hdmi_irq, IRQF_SHARED,
|
||||
@@ -1988,11 +1975,11 @@ int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
|
||||
hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE,
|
||||
HDMI_IH_PHY_STAT0);
|
||||
|
||||
- ret = dw_hdmi_fb_registered(hdmi);
|
||||
- if (ret)
|
||||
- goto err_iahb;
|
||||
+ hdmi->bridge.driver_private = hdmi;
|
||||
+ hdmi->bridge.funcs = &dw_hdmi_bridge_funcs;
|
||||
+ hdmi->bridge.of_node = pdev->dev.of_node;
|
||||
|
||||
- ret = dw_hdmi_register(encoder, hdmi);
|
||||
+ ret = dw_hdmi_fb_registered(hdmi);
|
||||
if (ret)
|
||||
goto err_iahb;
|
||||
|
||||
@@ -2041,7 +2028,7 @@ int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
|
||||
|
||||
platform_set_drvdata(pdev, hdmi);
|
||||
|
||||
- return 0;
|
||||
+ return hdmi;
|
||||
|
||||
err_iahb:
|
||||
if (hdmi->i2c) {
|
||||
@@ -2055,14 +2042,11 @@ int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
|
||||
err_res:
|
||||
i2c_put_adapter(hdmi->ddc);
|
||||
|
||||
- return ret;
|
||||
+ return ERR_PTR(ret);
|
||||
}
|
||||
-EXPORT_SYMBOL_GPL(dw_hdmi_bind);
|
||||
|
||||
-void dw_hdmi_unbind(struct device *dev)
|
||||
+static void __dw_hdmi_remove(struct dw_hdmi *hdmi)
|
||||
{
|
||||
- struct dw_hdmi *hdmi = dev_get_drvdata(dev);
|
||||
-
|
||||
if (hdmi->audio && !IS_ERR(hdmi->audio))
|
||||
platform_device_unregister(hdmi->audio);
|
||||
|
||||
@@ -2077,6 +2061,70 @@ void dw_hdmi_unbind(struct device *dev)
|
||||
else
|
||||
i2c_put_adapter(hdmi->ddc);
|
||||
}
|
||||
+
|
||||
+/* -----------------------------------------------------------------------------
|
||||
+ * Probe/remove API, used from platforms based on the DRM bridge API.
|
||||
+ */
|
||||
+int dw_hdmi_probe(struct platform_device *pdev,
|
||||
+ const struct dw_hdmi_plat_data *plat_data)
|
||||
+{
|
||||
+ struct dw_hdmi *hdmi;
|
||||
+ int ret;
|
||||
+
|
||||
+ hdmi = __dw_hdmi_probe(pdev, plat_data);
|
||||
+ if (IS_ERR(hdmi))
|
||||
+ return PTR_ERR(hdmi);
|
||||
+
|
||||
+ ret = drm_bridge_add(&hdmi->bridge);
|
||||
+ if (ret < 0) {
|
||||
+ __dw_hdmi_remove(hdmi);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(dw_hdmi_probe);
|
||||
+
|
||||
+void dw_hdmi_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct dw_hdmi *hdmi = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ drm_bridge_remove(&hdmi->bridge);
|
||||
+
|
||||
+ __dw_hdmi_remove(hdmi);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(dw_hdmi_remove);
|
||||
+
|
||||
+/* -----------------------------------------------------------------------------
|
||||
+ * Bind/unbind API, used from platforms based on the component framework.
|
||||
+ */
|
||||
+int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
|
||||
+ const struct dw_hdmi_plat_data *plat_data)
|
||||
+{
|
||||
+ struct dw_hdmi *hdmi;
|
||||
+ int ret;
|
||||
+
|
||||
+ hdmi = __dw_hdmi_probe(pdev, plat_data);
|
||||
+ if (IS_ERR(hdmi))
|
||||
+ return PTR_ERR(hdmi);
|
||||
+
|
||||
+ ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL);
|
||||
+ if (ret) {
|
||||
+ dw_hdmi_remove(pdev);
|
||||
+ DRM_ERROR("Failed to initialize bridge with drm\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(dw_hdmi_bind);
|
||||
+
|
||||
+void dw_hdmi_unbind(struct device *dev)
|
||||
+{
|
||||
+ struct dw_hdmi *hdmi = dev_get_drvdata(dev);
|
||||
+
|
||||
+ __dw_hdmi_remove(hdmi);
|
||||
+}
|
||||
EXPORT_SYMBOL_GPL(dw_hdmi_unbind);
|
||||
|
||||
MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
|
||||
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
|
||||
index 94ff6ed..3bb22a8 100644
|
||||
--- a/include/drm/bridge/dw_hdmi.h
|
||||
+++ b/include/drm/bridge/dw_hdmi.h
|
||||
@@ -56,6 +56,9 @@ struct dw_hdmi_plat_data {
|
||||
struct drm_display_mode *mode);
|
||||
};
|
||||
|
||||
+int dw_hdmi_probe(struct platform_device *pdev,
|
||||
+ const struct dw_hdmi_plat_data *plat_data);
|
||||
+void dw_hdmi_remove(struct platform_device *pdev);
|
||||
void dw_hdmi_unbind(struct device *dev);
|
||||
int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
|
||||
const struct dw_hdmi_plat_data *plat_data);
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
From 8fb0058965b30a39f1e0e3820b96013cfbf6bfc6 Mon Sep 17 00:00:00 2001
|
||||
From: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:29:01 +0200
|
||||
Subject: [PATCH 21/93] drm: bridge: dw-hdmi: Remove PHY configuration
|
||||
resolution parameter
|
||||
|
||||
The current code hard codes the call of hdmi_phy_configure() to be 8bpp
|
||||
and provides extraneous error checking to verify that this hardcoded
|
||||
value is correct. Simplify the implementation by removing the argument.
|
||||
|
||||
Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-12-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 27 +++++----------------------
|
||||
1 file changed, 5 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 107fea4..b4fb0bd 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -930,31 +930,14 @@ static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable)
|
||||
HDMI_PHY_CONF0_SELDIPIF_MASK);
|
||||
}
|
||||
|
||||
-static int hdmi_phy_configure(struct dw_hdmi *hdmi,
|
||||
- unsigned char res, int cscon)
|
||||
+static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon)
|
||||
{
|
||||
- unsigned res_idx;
|
||||
u8 val, msec;
|
||||
const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
|
||||
const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg;
|
||||
const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
|
||||
const struct dw_hdmi_phy_config *phy_config = pdata->phy_config;
|
||||
|
||||
- switch (res) {
|
||||
- case 0: /* color resolution 0 is 8 bit colour depth */
|
||||
- case 8:
|
||||
- res_idx = DW_HDMI_RES_8;
|
||||
- break;
|
||||
- case 10:
|
||||
- res_idx = DW_HDMI_RES_10;
|
||||
- break;
|
||||
- case 12:
|
||||
- res_idx = DW_HDMI_RES_12;
|
||||
- break;
|
||||
- default:
|
||||
- return -EINVAL;
|
||||
- }
|
||||
-
|
||||
/* PLL/MPLL Cfg - always match on final entry */
|
||||
for (; mpll_config->mpixelclock != ~0UL; mpll_config++)
|
||||
if (hdmi->hdmi_data.video_mode.mpixelclock <=
|
||||
@@ -1004,11 +987,11 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi,
|
||||
HDMI_PHY_I2CM_SLAVE_ADDR);
|
||||
hdmi_phy_test_clear(hdmi, 0);
|
||||
|
||||
- hdmi_phy_i2c_write(hdmi, mpll_config->res[res_idx].cpce, 0x06);
|
||||
- hdmi_phy_i2c_write(hdmi, mpll_config->res[res_idx].gmp, 0x15);
|
||||
+ hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce, 0x06);
|
||||
+ hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp, 0x15);
|
||||
|
||||
/* CURRCTRL */
|
||||
- hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[res_idx], 0x10);
|
||||
+ hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0], 0x10);
|
||||
|
||||
hdmi_phy_i2c_write(hdmi, 0x0000, 0x13); /* PLLPHBYCTRL */
|
||||
hdmi_phy_i2c_write(hdmi, 0x0006, 0x17);
|
||||
@@ -1068,7 +1051,7 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
|
||||
dw_hdmi_phy_enable_powerdown(hdmi, true);
|
||||
|
||||
/* Enable CSC */
|
||||
- ret = hdmi_phy_configure(hdmi, 8, cscon);
|
||||
+ ret = hdmi_phy_configure(hdmi, cscon);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
From c7604b72b3695ee449d16916aa474b23c53af425 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:29:02 +0200
|
||||
Subject: [PATCH 22/93] drm: bridge: dw-hdmi: Rename CONF0 SPARECTRL bit to
|
||||
SVSRET
|
||||
|
||||
The bit is documented in a Rockchip BSP as
|
||||
|
||||
#define m_SVSRET_SIG (1 << 5) /* depend on PHY_MHL_COMB0=1 */
|
||||
|
||||
This is confirmed by a Renesas platform, which uses a 2.0 DWC HDMI TX as
|
||||
the RK3288. Rename the bit accordingly.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-13-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 8 ++++----
|
||||
drivers/gpu/drm/bridge/dw-hdmi.h | 4 ++--
|
||||
2 files changed, 6 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index b4fb0bd..06c252f 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -895,11 +895,11 @@ static void dw_hdmi_phy_enable_tmds(struct dw_hdmi *hdmi, u8 enable)
|
||||
HDMI_PHY_CONF0_ENTMDS_MASK);
|
||||
}
|
||||
|
||||
-static void dw_hdmi_phy_enable_spare(struct dw_hdmi *hdmi, u8 enable)
|
||||
+static void dw_hdmi_phy_enable_svsret(struct dw_hdmi *hdmi, u8 enable)
|
||||
{
|
||||
hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
|
||||
- HDMI_PHY_CONF0_SPARECTRL_OFFSET,
|
||||
- HDMI_PHY_CONF0_SPARECTRL_MASK);
|
||||
+ HDMI_PHY_CONF0_SVSRET_OFFSET,
|
||||
+ HDMI_PHY_CONF0_SVSRET_MASK);
|
||||
}
|
||||
|
||||
static void dw_hdmi_phy_gen2_pddq(struct dw_hdmi *hdmi, u8 enable)
|
||||
@@ -1014,7 +1014,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon)
|
||||
dw_hdmi_phy_gen2_pddq(hdmi, 0);
|
||||
|
||||
if (hdmi->dev_type == RK3288_HDMI)
|
||||
- dw_hdmi_phy_enable_spare(hdmi, 1);
|
||||
+ dw_hdmi_phy_enable_svsret(hdmi, 1);
|
||||
|
||||
/*Wait for PHY PLL lock */
|
||||
msec = 5;
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.h b/drivers/gpu/drm/bridge/dw-hdmi.h
|
||||
index 55135bb..08235ae 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.h
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.h
|
||||
@@ -847,8 +847,8 @@ enum {
|
||||
HDMI_PHY_CONF0_PDZ_OFFSET = 7,
|
||||
HDMI_PHY_CONF0_ENTMDS_MASK = 0x40,
|
||||
HDMI_PHY_CONF0_ENTMDS_OFFSET = 6,
|
||||
- HDMI_PHY_CONF0_SPARECTRL_MASK = 0x20,
|
||||
- HDMI_PHY_CONF0_SPARECTRL_OFFSET = 5,
|
||||
+ HDMI_PHY_CONF0_SVSRET_MASK = 0x20,
|
||||
+ HDMI_PHY_CONF0_SVSRET_OFFSET = 5,
|
||||
HDMI_PHY_CONF0_GEN2_PDDQ_MASK = 0x10,
|
||||
HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET = 4,
|
||||
HDMI_PHY_CONF0_GEN2_TXPWRON_MASK = 0x8,
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
From a2bdacb64471d710bb4bdbc70e27d276eaae6d00 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:29:03 +0200
|
||||
Subject: [PATCH 23/93] drm: bridge: dw-hdmi: Reject invalid product IDs
|
||||
|
||||
The DWC HDMI TX can be recognized by the two product identification
|
||||
registers. If the registers don't read as expect the IP will be very
|
||||
different than what the driver has been designed for, or will be
|
||||
misconfigured in a way that makes it non-operational (invalid memory
|
||||
address, incorrect clocks, ...). We should reject this situation with an
|
||||
error.
|
||||
|
||||
While this isn't critical for proper operation with supported IPs at the
|
||||
moment, the driver will soon gain automatic device-specific handling
|
||||
based on runtime device identification. This change makes it easier to
|
||||
implement that without having to default to a random guess in case the
|
||||
device can't be identified.
|
||||
|
||||
While at it print a readable version number in the device identification
|
||||
message instead of raw register values.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-14-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 25 +++++++++++++++++++------
|
||||
drivers/gpu/drm/bridge/dw-hdmi.h | 8 ++++++++
|
||||
2 files changed, 27 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 06c252f..1809247 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -1832,6 +1832,9 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
int irq;
|
||||
int ret;
|
||||
u32 val = 1;
|
||||
+ u16 version;
|
||||
+ u8 prod_id0;
|
||||
+ u8 prod_id1;
|
||||
u8 config0;
|
||||
u8 config1;
|
||||
|
||||
@@ -1914,12 +1917,22 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
}
|
||||
|
||||
/* Product and revision IDs */
|
||||
- dev_info(dev,
|
||||
- "Detected HDMI controller 0x%x:0x%x:0x%x:0x%x\n",
|
||||
- hdmi_readb(hdmi, HDMI_DESIGN_ID),
|
||||
- hdmi_readb(hdmi, HDMI_REVISION_ID),
|
||||
- hdmi_readb(hdmi, HDMI_PRODUCT_ID0),
|
||||
- hdmi_readb(hdmi, HDMI_PRODUCT_ID1));
|
||||
+ version = (hdmi_readb(hdmi, HDMI_DESIGN_ID) << 8)
|
||||
+ | (hdmi_readb(hdmi, HDMI_REVISION_ID) << 0);
|
||||
+ prod_id0 = hdmi_readb(hdmi, HDMI_PRODUCT_ID0);
|
||||
+ prod_id1 = hdmi_readb(hdmi, HDMI_PRODUCT_ID1);
|
||||
+
|
||||
+ if (prod_id0 != HDMI_PRODUCT_ID0_HDMI_TX ||
|
||||
+ (prod_id1 & ~HDMI_PRODUCT_ID1_HDCP) != HDMI_PRODUCT_ID1_HDMI_TX) {
|
||||
+ dev_err(dev, "Unsupported HDMI controller (%04x:%02x:%02x)\n",
|
||||
+ version, prod_id0, prod_id1);
|
||||
+ ret = -ENODEV;
|
||||
+ goto err_iahb;
|
||||
+ }
|
||||
+
|
||||
+ dev_info(dev, "Detected HDMI TX controller v%x.%03x %s HDCP\n",
|
||||
+ version >> 12, version & 0xfff,
|
||||
+ prod_id1 & HDMI_PRODUCT_ID1_HDCP ? "with" : "without");
|
||||
|
||||
initialize_hdmi_ih_mutes(hdmi);
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.h b/drivers/gpu/drm/bridge/dw-hdmi.h
|
||||
index 08235ae..91d7fab 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.h
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.h
|
||||
@@ -545,6 +545,14 @@
|
||||
#define HDMI_I2CM_FS_SCL_LCNT_0_ADDR 0x7E12
|
||||
|
||||
enum {
|
||||
+/* PRODUCT_ID0 field values */
|
||||
+ HDMI_PRODUCT_ID0_HDMI_TX = 0xa0,
|
||||
+
|
||||
+/* PRODUCT_ID1 field values */
|
||||
+ HDMI_PRODUCT_ID1_HDCP = 0xc0,
|
||||
+ HDMI_PRODUCT_ID1_HDMI_RX = 0x02,
|
||||
+ HDMI_PRODUCT_ID1_HDMI_TX = 0x01,
|
||||
+
|
||||
/* CONFIG0_ID field values */
|
||||
HDMI_CONFIG0_I2S = 0x10,
|
||||
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
From dce4baf82ad245b9fc6a6fe6945e484ac9f32fa4 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:29:04 +0200
|
||||
Subject: [PATCH 24/93] drm: bridge: dw-hdmi: Detect AHB audio DMA using
|
||||
correct register
|
||||
|
||||
Bit 0 in CONFIG1_ID tells whether the IP core uses an AHB slave
|
||||
interface for control. The correct way to identify AHB audio DMA support
|
||||
is through bit 1 in CONFIG3_ID.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-15-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 6 +++---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.h | 4 ++++
|
||||
2 files changed, 7 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 1809247..730a7558 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -1836,7 +1836,7 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
u8 prod_id0;
|
||||
u8 prod_id1;
|
||||
u8 config0;
|
||||
- u8 config1;
|
||||
+ u8 config3;
|
||||
|
||||
hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
|
||||
if (!hdmi)
|
||||
@@ -1988,9 +1988,9 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
pdevinfo.id = PLATFORM_DEVID_AUTO;
|
||||
|
||||
config0 = hdmi_readb(hdmi, HDMI_CONFIG0_ID);
|
||||
- config1 = hdmi_readb(hdmi, HDMI_CONFIG1_ID);
|
||||
+ config3 = hdmi_readb(hdmi, HDMI_CONFIG3_ID);
|
||||
|
||||
- if (config1 & HDMI_CONFIG1_AHB) {
|
||||
+ if (config3 & HDMI_CONFIG3_AHBAUDDMA) {
|
||||
struct dw_hdmi_audio_data audio;
|
||||
|
||||
audio.phys = iores->start;
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.h b/drivers/gpu/drm/bridge/dw-hdmi.h
|
||||
index 91d7fab..a4fd64a 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.h
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.h
|
||||
@@ -559,6 +559,10 @@ enum {
|
||||
/* CONFIG1_ID field values */
|
||||
HDMI_CONFIG1_AHB = 0x01,
|
||||
|
||||
+/* CONFIG3_ID field values */
|
||||
+ HDMI_CONFIG3_AHBAUDDMA = 0x02,
|
||||
+ HDMI_CONFIG3_GPAUD = 0x01,
|
||||
+
|
||||
/* IH_FC_INT2 field values */
|
||||
HDMI_IH_FC_INT2_OVERFLOW_MASK = 0x03,
|
||||
HDMI_IH_FC_INT2_LOW_PRIORITY_OVERFLOW = 0x02,
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
From 3b3c8dc7038a16dfeb29388d6b5afbef869ebc2d Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:29:05 +0200
|
||||
Subject: [PATCH 25/93] drm: bridge: dw-hdmi: Handle overflow workaround based
|
||||
on device version
|
||||
|
||||
Use the device version queried at runtime instead of the device type
|
||||
provided through platform data to handle the overflow workaround. This
|
||||
will make support of other SoCs integrating the same HDMI TX controller
|
||||
version easier.
|
||||
|
||||
Among the supported platforms only i.MX6DL and i.MX6Q have been
|
||||
identified as needing the workaround. Disabling it on Rockchip RK3288
|
||||
(which integrates a v2.00a controller) didn't produce any error or
|
||||
artifact.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-16-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 46 ++++++++++++++++++++++++++++------------
|
||||
1 file changed, 33 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 730a7558..f4faa14 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -117,8 +117,10 @@ struct dw_hdmi {
|
||||
struct drm_connector connector;
|
||||
struct drm_bridge bridge;
|
||||
|
||||
- struct platform_device *audio;
|
||||
enum dw_hdmi_devtype dev_type;
|
||||
+ unsigned int version;
|
||||
+
|
||||
+ struct platform_device *audio;
|
||||
struct device *dev;
|
||||
struct clk *isfr_clk;
|
||||
struct clk *iahb_clk;
|
||||
@@ -1323,19 +1325,38 @@ static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi)
|
||||
/* Workaround to clear the overflow condition */
|
||||
static void dw_hdmi_clear_overflow(struct dw_hdmi *hdmi)
|
||||
{
|
||||
- int count;
|
||||
+ unsigned int count;
|
||||
+ unsigned int i;
|
||||
u8 val;
|
||||
|
||||
- /* TMDS software reset */
|
||||
- hdmi_writeb(hdmi, (u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, HDMI_MC_SWRSTZ);
|
||||
+ /*
|
||||
+ * Under some circumstances the Frame Composer arithmetic unit can miss
|
||||
+ * an FC register write due to being busy processing the previous one.
|
||||
+ * The issue can be worked around by issuing a TMDS software reset and
|
||||
+ * then write one of the FC registers several times.
|
||||
+ *
|
||||
+ * The number of iterations matters and depends on the HDMI TX revision
|
||||
+ * (and possibly on the platform). So far only i.MX6Q (v1.30a) and
|
||||
+ * i.MX6DL (v1.31a) have been identified as needing the workaround, with
|
||||
+ * 4 and 1 iterations respectively.
|
||||
+ */
|
||||
|
||||
- val = hdmi_readb(hdmi, HDMI_FC_INVIDCONF);
|
||||
- if (hdmi->dev_type == IMX6DL_HDMI) {
|
||||
- hdmi_writeb(hdmi, val, HDMI_FC_INVIDCONF);
|
||||
+ switch (hdmi->version) {
|
||||
+ case 0x130a:
|
||||
+ count = 4;
|
||||
+ break;
|
||||
+ case 0x131a:
|
||||
+ count = 1;
|
||||
+ break;
|
||||
+ default:
|
||||
return;
|
||||
}
|
||||
|
||||
- for (count = 0; count < 4; count++)
|
||||
+ /* TMDS software reset */
|
||||
+ hdmi_writeb(hdmi, (u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, HDMI_MC_SWRSTZ);
|
||||
+
|
||||
+ val = hdmi_readb(hdmi, HDMI_FC_INVIDCONF);
|
||||
+ for (i = 0; i < count; i++)
|
||||
hdmi_writeb(hdmi, val, HDMI_FC_INVIDCONF);
|
||||
}
|
||||
|
||||
@@ -1832,7 +1853,6 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
int irq;
|
||||
int ret;
|
||||
u32 val = 1;
|
||||
- u16 version;
|
||||
u8 prod_id0;
|
||||
u8 prod_id1;
|
||||
u8 config0;
|
||||
@@ -1917,21 +1937,21 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
}
|
||||
|
||||
/* Product and revision IDs */
|
||||
- version = (hdmi_readb(hdmi, HDMI_DESIGN_ID) << 8)
|
||||
- | (hdmi_readb(hdmi, HDMI_REVISION_ID) << 0);
|
||||
+ hdmi->version = (hdmi_readb(hdmi, HDMI_DESIGN_ID) << 8)
|
||||
+ | (hdmi_readb(hdmi, HDMI_REVISION_ID) << 0);
|
||||
prod_id0 = hdmi_readb(hdmi, HDMI_PRODUCT_ID0);
|
||||
prod_id1 = hdmi_readb(hdmi, HDMI_PRODUCT_ID1);
|
||||
|
||||
if (prod_id0 != HDMI_PRODUCT_ID0_HDMI_TX ||
|
||||
(prod_id1 & ~HDMI_PRODUCT_ID1_HDCP) != HDMI_PRODUCT_ID1_HDMI_TX) {
|
||||
dev_err(dev, "Unsupported HDMI controller (%04x:%02x:%02x)\n",
|
||||
- version, prod_id0, prod_id1);
|
||||
+ hdmi->version, prod_id0, prod_id1);
|
||||
ret = -ENODEV;
|
||||
goto err_iahb;
|
||||
}
|
||||
|
||||
dev_info(dev, "Detected HDMI TX controller v%x.%03x %s HDCP\n",
|
||||
- version >> 12, version & 0xfff,
|
||||
+ hdmi->version >> 12, hdmi->version & 0xfff,
|
||||
prod_id1 & HDMI_PRODUCT_ID1_HDCP ? "with" : "without");
|
||||
|
||||
initialize_hdmi_ih_mutes(hdmi);
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,149 @@
|
|||
From c69ce1e08f7d1eeb8de98544ecc1c1c12fe91408 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:29:06 +0200
|
||||
Subject: [PATCH 26/93] drm: bridge: dw-hdmi: Detect PHY type at runtime
|
||||
|
||||
Detect the PHY type and use it to handle the PHY type-specific SVSRET
|
||||
signal.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-17-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 68 ++++++++++++++++++++++++++++++++++++++--
|
||||
include/drm/bridge/dw_hdmi.h | 10 ++++++
|
||||
2 files changed, 75 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index f4faa14..ef4f2f9 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -113,6 +113,12 @@ struct dw_hdmi_i2c {
|
||||
bool is_regaddr;
|
||||
};
|
||||
|
||||
+struct dw_hdmi_phy_data {
|
||||
+ enum dw_hdmi_phy_type type;
|
||||
+ const char *name;
|
||||
+ bool has_svsret;
|
||||
+};
|
||||
+
|
||||
struct dw_hdmi {
|
||||
struct drm_connector connector;
|
||||
struct drm_bridge bridge;
|
||||
@@ -134,7 +140,9 @@ struct dw_hdmi {
|
||||
u8 edid[HDMI_EDID_LEN];
|
||||
bool cable_plugin;
|
||||
|
||||
+ const struct dw_hdmi_phy_data *phy;
|
||||
bool phy_enabled;
|
||||
+
|
||||
struct drm_display_mode previous_mode;
|
||||
|
||||
struct i2c_adapter *ddc;
|
||||
@@ -1015,7 +1023,8 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon)
|
||||
dw_hdmi_phy_gen2_txpwron(hdmi, 1);
|
||||
dw_hdmi_phy_gen2_pddq(hdmi, 0);
|
||||
|
||||
- if (hdmi->dev_type == RK3288_HDMI)
|
||||
+ /* The DWC MHL and HDMI 2.0 PHYs need the SVSRET signal to be set. */
|
||||
+ if (hdmi->phy->has_svsret)
|
||||
dw_hdmi_phy_enable_svsret(hdmi, 1);
|
||||
|
||||
/*Wait for PHY PLL lock */
|
||||
@@ -1840,6 +1849,54 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
+static const struct dw_hdmi_phy_data dw_hdmi_phys[] = {
|
||||
+ {
|
||||
+ .type = DW_HDMI_PHY_DWC_HDMI_TX_PHY,
|
||||
+ .name = "DWC HDMI TX PHY",
|
||||
+ }, {
|
||||
+ .type = DW_HDMI_PHY_DWC_MHL_PHY_HEAC,
|
||||
+ .name = "DWC MHL PHY + HEAC PHY",
|
||||
+ .has_svsret = true,
|
||||
+ }, {
|
||||
+ .type = DW_HDMI_PHY_DWC_MHL_PHY,
|
||||
+ .name = "DWC MHL PHY",
|
||||
+ .has_svsret = true,
|
||||
+ }, {
|
||||
+ .type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY_HEAC,
|
||||
+ .name = "DWC HDMI 3D TX PHY + HEAC PHY",
|
||||
+ }, {
|
||||
+ .type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY,
|
||||
+ .name = "DWC HDMI 3D TX PHY",
|
||||
+ }, {
|
||||
+ .type = DW_HDMI_PHY_DWC_HDMI20_TX_PHY,
|
||||
+ .name = "DWC HDMI 2.0 TX PHY",
|
||||
+ .has_svsret = true,
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
|
||||
+{
|
||||
+ unsigned int i;
|
||||
+ u8 phy_type;
|
||||
+
|
||||
+ phy_type = hdmi_readb(hdmi, HDMI_CONFIG2_ID);
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(dw_hdmi_phys); ++i) {
|
||||
+ if (dw_hdmi_phys[i].type == phy_type) {
|
||||
+ hdmi->phy = &dw_hdmi_phys[i];
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (phy_type == DW_HDMI_PHY_VENDOR_PHY)
|
||||
+ dev_err(hdmi->dev, "Unsupported vendor HDMI PHY\n");
|
||||
+ else
|
||||
+ dev_err(hdmi->dev, "Unsupported HDMI PHY type (%02x)\n",
|
||||
+ phy_type);
|
||||
+
|
||||
+ return -ENODEV;
|
||||
+}
|
||||
+
|
||||
static struct dw_hdmi *
|
||||
__dw_hdmi_probe(struct platform_device *pdev,
|
||||
const struct dw_hdmi_plat_data *plat_data)
|
||||
@@ -1950,9 +2007,14 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
goto err_iahb;
|
||||
}
|
||||
|
||||
- dev_info(dev, "Detected HDMI TX controller v%x.%03x %s HDCP\n",
|
||||
+ ret = dw_hdmi_detect_phy(hdmi);
|
||||
+ if (ret < 0)
|
||||
+ goto err_iahb;
|
||||
+
|
||||
+ dev_info(dev, "Detected HDMI TX controller v%x.%03x %s HDCP (%s)\n",
|
||||
hdmi->version >> 12, hdmi->version & 0xfff,
|
||||
- prod_id1 & HDMI_PRODUCT_ID1_HDCP ? "with" : "without");
|
||||
+ prod_id1 & HDMI_PRODUCT_ID1_HDCP ? "with" : "without",
|
||||
+ hdmi->phy->name);
|
||||
|
||||
initialize_hdmi_ih_mutes(hdmi);
|
||||
|
||||
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
|
||||
index 3bb22a8..b080a17 100644
|
||||
--- a/include/drm/bridge/dw_hdmi.h
|
||||
+++ b/include/drm/bridge/dw_hdmi.h
|
||||
@@ -27,6 +27,16 @@ enum dw_hdmi_devtype {
|
||||
RK3288_HDMI,
|
||||
};
|
||||
|
||||
+enum dw_hdmi_phy_type {
|
||||
+ DW_HDMI_PHY_DWC_HDMI_TX_PHY = 0x00,
|
||||
+ DW_HDMI_PHY_DWC_MHL_PHY_HEAC = 0xb2,
|
||||
+ DW_HDMI_PHY_DWC_MHL_PHY = 0xc2,
|
||||
+ DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY_HEAC = 0xe2,
|
||||
+ DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY = 0xf2,
|
||||
+ DW_HDMI_PHY_DWC_HDMI20_TX_PHY = 0xf3,
|
||||
+ DW_HDMI_PHY_VENDOR_PHY = 0xfe,
|
||||
+};
|
||||
+
|
||||
struct dw_hdmi_mpll_config {
|
||||
unsigned long mpixelclock;
|
||||
struct {
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
From d7ce5ad1e16494b6881a9b3e641f224f5d27597b Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:29:07 +0200
|
||||
Subject: [PATCH 27/93] drm: bridge: dw-hdmi: Define and use macros for PHY
|
||||
register addresses
|
||||
|
||||
Replace the hardcoded register address numerical values with macros to
|
||||
clarify the code.
|
||||
|
||||
This change has been tested by comparing the assembly code before and
|
||||
after the change.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-18-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 35 ++++++++++++---------
|
||||
drivers/gpu/drm/bridge/dw-hdmi.h | 66 ++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 86 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index ef4f2f9..6e605fd 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -997,21 +997,26 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon)
|
||||
HDMI_PHY_I2CM_SLAVE_ADDR);
|
||||
hdmi_phy_test_clear(hdmi, 0);
|
||||
|
||||
- hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce, 0x06);
|
||||
- hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp, 0x15);
|
||||
-
|
||||
- /* CURRCTRL */
|
||||
- hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0], 0x10);
|
||||
-
|
||||
- hdmi_phy_i2c_write(hdmi, 0x0000, 0x13); /* PLLPHBYCTRL */
|
||||
- hdmi_phy_i2c_write(hdmi, 0x0006, 0x17);
|
||||
-
|
||||
- hdmi_phy_i2c_write(hdmi, phy_config->term, 0x19); /* TXTERM */
|
||||
- hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr, 0x09); /* CKSYMTXCTRL */
|
||||
- hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr, 0x0E); /* VLEVCTRL */
|
||||
-
|
||||
- /* REMOVE CLK TERM */
|
||||
- hdmi_phy_i2c_write(hdmi, 0x8000, 0x05); /* CKCALCTRL */
|
||||
+ hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce,
|
||||
+ HDMI_3D_TX_PHY_CPCE_CTRL);
|
||||
+ hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp,
|
||||
+ HDMI_3D_TX_PHY_GMPCTRL);
|
||||
+ hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0],
|
||||
+ HDMI_3D_TX_PHY_CURRCTRL);
|
||||
+
|
||||
+ hdmi_phy_i2c_write(hdmi, 0, HDMI_3D_TX_PHY_PLLPHBYCTRL);
|
||||
+ hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_FB_CLK,
|
||||
+ HDMI_3D_TX_PHY_MSM_CTRL);
|
||||
+
|
||||
+ hdmi_phy_i2c_write(hdmi, phy_config->term, HDMI_3D_TX_PHY_TXTERM);
|
||||
+ hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr,
|
||||
+ HDMI_3D_TX_PHY_CKSYMTXCTRL);
|
||||
+ hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr,
|
||||
+ HDMI_3D_TX_PHY_VLEVCTRL);
|
||||
+
|
||||
+ /* Override and disable clock termination. */
|
||||
+ hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE,
|
||||
+ HDMI_3D_TX_PHY_CKCALCTRL);
|
||||
|
||||
dw_hdmi_phy_enable_powerdown(hdmi, false);
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.h b/drivers/gpu/drm/bridge/dw-hdmi.h
|
||||
index a4fd64a..f3c149c 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.h
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.h
|
||||
@@ -1085,4 +1085,70 @@ enum {
|
||||
HDMI_I2CM_CTLINT_ARB_MASK = 0x4,
|
||||
};
|
||||
|
||||
+/*
|
||||
+ * HDMI 3D TX PHY registers
|
||||
+ */
|
||||
+#define HDMI_3D_TX_PHY_PWRCTRL 0x00
|
||||
+#define HDMI_3D_TX_PHY_SERDIVCTRL 0x01
|
||||
+#define HDMI_3D_TX_PHY_SERCKCTRL 0x02
|
||||
+#define HDMI_3D_TX_PHY_SERCKKILLCTRL 0x03
|
||||
+#define HDMI_3D_TX_PHY_TXRESCTRL 0x04
|
||||
+#define HDMI_3D_TX_PHY_CKCALCTRL 0x05
|
||||
+#define HDMI_3D_TX_PHY_CPCE_CTRL 0x06
|
||||
+#define HDMI_3D_TX_PHY_TXCLKMEASCTRL 0x07
|
||||
+#define HDMI_3D_TX_PHY_TXMEASCTRL 0x08
|
||||
+#define HDMI_3D_TX_PHY_CKSYMTXCTRL 0x09
|
||||
+#define HDMI_3D_TX_PHY_CMPSEQCTRL 0x0a
|
||||
+#define HDMI_3D_TX_PHY_CMPPWRCTRL 0x0b
|
||||
+#define HDMI_3D_TX_PHY_CMPMODECTRL 0x0c
|
||||
+#define HDMI_3D_TX_PHY_MEASCTRL 0x0d
|
||||
+#define HDMI_3D_TX_PHY_VLEVCTRL 0x0e
|
||||
+#define HDMI_3D_TX_PHY_D2ACTRL 0x0f
|
||||
+#define HDMI_3D_TX_PHY_CURRCTRL 0x10
|
||||
+#define HDMI_3D_TX_PHY_DRVANACTRL 0x11
|
||||
+#define HDMI_3D_TX_PHY_PLLMEASCTRL 0x12
|
||||
+#define HDMI_3D_TX_PHY_PLLPHBYCTRL 0x13
|
||||
+#define HDMI_3D_TX_PHY_GRP_CTRL 0x14
|
||||
+#define HDMI_3D_TX_PHY_GMPCTRL 0x15
|
||||
+#define HDMI_3D_TX_PHY_MPLLMEASCTRL 0x16
|
||||
+#define HDMI_3D_TX_PHY_MSM_CTRL 0x17
|
||||
+#define HDMI_3D_TX_PHY_SCRPB_STATUS 0x18
|
||||
+#define HDMI_3D_TX_PHY_TXTERM 0x19
|
||||
+#define HDMI_3D_TX_PHY_PTRPT_ENBL 0x1a
|
||||
+#define HDMI_3D_TX_PHY_PATTERNGEN 0x1b
|
||||
+#define HDMI_3D_TX_PHY_SDCAP_MODE 0x1c
|
||||
+#define HDMI_3D_TX_PHY_SCOPEMODE 0x1d
|
||||
+#define HDMI_3D_TX_PHY_DIGTXMODE 0x1e
|
||||
+#define HDMI_3D_TX_PHY_STR_STATUS 0x1f
|
||||
+#define HDMI_3D_TX_PHY_SCOPECNT0 0x20
|
||||
+#define HDMI_3D_TX_PHY_SCOPECNT1 0x21
|
||||
+#define HDMI_3D_TX_PHY_SCOPECNT2 0x22
|
||||
+#define HDMI_3D_TX_PHY_SCOPECNTCLK 0x23
|
||||
+#define HDMI_3D_TX_PHY_SCOPESAMPLE 0x24
|
||||
+#define HDMI_3D_TX_PHY_SCOPECNTMSB01 0x25
|
||||
+#define HDMI_3D_TX_PHY_SCOPECNTMSB2CK 0x26
|
||||
+
|
||||
+/* HDMI_3D_TX_PHY_CKCALCTRL values */
|
||||
+#define HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE BIT(15)
|
||||
+
|
||||
+/* HDMI_3D_TX_PHY_MSM_CTRL values */
|
||||
+#define HDMI_3D_TX_PHY_MSM_CTRL_MPLL_PH_SEL_CK BIT(13)
|
||||
+#define HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_CLK_REF_MPLL (0 << 1)
|
||||
+#define HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_OFF (1 << 1)
|
||||
+#define HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_PCLK (2 << 1)
|
||||
+#define HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_FB_CLK (3 << 1)
|
||||
+#define HDMI_3D_TX_PHY_MSM_CTRL_SCOPE_CK_SEL BIT(0)
|
||||
+
|
||||
+/* HDMI_3D_TX_PHY_PTRPT_ENBL values */
|
||||
+#define HDMI_3D_TX_PHY_PTRPT_ENBL_OVERRIDE BIT(15)
|
||||
+#define HDMI_3D_TX_PHY_PTRPT_ENBL_PG_SKIP_BIT2 BIT(8)
|
||||
+#define HDMI_3D_TX_PHY_PTRPT_ENBL_PG_SKIP_BIT1 BIT(7)
|
||||
+#define HDMI_3D_TX_PHY_PTRPT_ENBL_PG_SKIP_BIT0 BIT(6)
|
||||
+#define HDMI_3D_TX_PHY_PTRPT_ENBL_CK_REF_ENB BIT(5)
|
||||
+#define HDMI_3D_TX_PHY_PTRPT_ENBL_RCAL_ENB BIT(4)
|
||||
+#define HDMI_3D_TX_PHY_PTRPT_ENBL_TX_CLK_ALIGN_ENB BIT(3)
|
||||
+#define HDMI_3D_TX_PHY_PTRPT_ENBL_TX_READY BIT(2)
|
||||
+#define HDMI_3D_TX_PHY_PTRPT_ENBL_CKO_WORD_ENB BIT(1)
|
||||
+#define HDMI_3D_TX_PHY_PTRPT_ENBL_REFCLK_ENB BIT(0)
|
||||
+
|
||||
#endif /* __DW_HDMI_H__ */
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
From 9e151c1acfd889a938f6f49bb07b14c101fa56d5 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:29:08 +0200
|
||||
Subject: [PATCH 28/93] drm: bridge: dw-hdmi: Fix the name of the PHY reset
|
||||
macros
|
||||
|
||||
The PHY reset signal is controlled by bit PHYRSTZ in the MC_PHYRSTZ
|
||||
register. The signal is active low on Gen1 PHYs and active high on Gen2
|
||||
PHYs. The driver toggles the signal high then low, which is correct for
|
||||
all currently supported platforms, but the register values macros are
|
||||
incorrectly named. Replace them with a single macro named after the bit,
|
||||
and add a comment to the source code to explain the behaviour.
|
||||
|
||||
The driver's behaviour isn't changed by this rename, the code will still
|
||||
need to be fixed to support Gen1 PHYs.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-19-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 6 +++---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.h | 3 +--
|
||||
2 files changed, 4 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 6e605fd..93e8816 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -986,9 +986,9 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon)
|
||||
/* gen2 pddq */
|
||||
dw_hdmi_phy_gen2_pddq(hdmi, 1);
|
||||
|
||||
- /* PHY reset */
|
||||
- hdmi_writeb(hdmi, HDMI_MC_PHYRSTZ_DEASSERT, HDMI_MC_PHYRSTZ);
|
||||
- hdmi_writeb(hdmi, HDMI_MC_PHYRSTZ_ASSERT, HDMI_MC_PHYRSTZ);
|
||||
+ /* PHY reset. The reset signal is active high on Gen2 PHYs. */
|
||||
+ hdmi_writeb(hdmi, HDMI_MC_PHYRSTZ_PHYRSTZ, HDMI_MC_PHYRSTZ);
|
||||
+ hdmi_writeb(hdmi, 0, HDMI_MC_PHYRSTZ);
|
||||
|
||||
hdmi_writeb(hdmi, HDMI_MC_HEACPHY_RST_ASSERT, HDMI_MC_HEACPHY_RST);
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.h b/drivers/gpu/drm/bridge/dw-hdmi.h
|
||||
index f3c149c..325b0b8 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.h
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.h
|
||||
@@ -989,8 +989,7 @@ enum {
|
||||
HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS = 0x0,
|
||||
|
||||
/* MC_PHYRSTZ field values */
|
||||
- HDMI_MC_PHYRSTZ_ASSERT = 0x0,
|
||||
- HDMI_MC_PHYRSTZ_DEASSERT = 0x1,
|
||||
+ HDMI_MC_PHYRSTZ_PHYRSTZ = 0x01,
|
||||
|
||||
/* MC_HEACPHY_RST field values */
|
||||
HDMI_MC_HEACPHY_RST_ASSERT = 0x1,
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
From 9faac4dec35ecb92a6eb348a0904b5484b89df72 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:29:09 +0200
|
||||
Subject: [PATCH 29/93] drm: bridge: dw-hdmi: Assert SVSRET before resetting
|
||||
the PHY
|
||||
|
||||
According to the PHY IP core vendor, the SVSRET signal must be asserted
|
||||
before resetting the PHY. Tests on RK3288 and R-Car Gen3 showed no
|
||||
regression, the change should thus be safe.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-20-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 10 +++++-----
|
||||
1 file changed, 5 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 93e8816..4fda071 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -986,6 +986,10 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon)
|
||||
/* gen2 pddq */
|
||||
dw_hdmi_phy_gen2_pddq(hdmi, 1);
|
||||
|
||||
+ /* Leave low power consumption mode by asserting SVSRET. */
|
||||
+ if (hdmi->phy->has_svsret)
|
||||
+ dw_hdmi_phy_enable_svsret(hdmi, 1);
|
||||
+
|
||||
/* PHY reset. The reset signal is active high on Gen2 PHYs. */
|
||||
hdmi_writeb(hdmi, HDMI_MC_PHYRSTZ_PHYRSTZ, HDMI_MC_PHYRSTZ);
|
||||
hdmi_writeb(hdmi, 0, HDMI_MC_PHYRSTZ);
|
||||
@@ -1028,11 +1032,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon)
|
||||
dw_hdmi_phy_gen2_txpwron(hdmi, 1);
|
||||
dw_hdmi_phy_gen2_pddq(hdmi, 0);
|
||||
|
||||
- /* The DWC MHL and HDMI 2.0 PHYs need the SVSRET signal to be set. */
|
||||
- if (hdmi->phy->has_svsret)
|
||||
- dw_hdmi_phy_enable_svsret(hdmi, 1);
|
||||
-
|
||||
- /*Wait for PHY PLL lock */
|
||||
+ /* Wait for PHY PLL lock */
|
||||
msec = 5;
|
||||
do {
|
||||
val = hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
From e9b6ad390a468f272176a6ceb103d63a46094be4 Mon Sep 17 00:00:00 2001
|
||||
From: Arnd Bergmann <arnd@arndb.de>
|
||||
Date: Mon, 23 Jan 2017 13:20:38 +0100
|
||||
Subject: [PATCH 30/93] drm: bridge: dw-hdmi: fix building without CONFIG_OF
|
||||
|
||||
The of_node member in struct drm_bridge is hidden when CONFIG_OF
|
||||
is disabled, causing a build error:
|
||||
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c: In function '__dw_hdmi_probe':
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c:2063:14: error: 'struct drm_bridge' has no member named 'of_node'
|
||||
|
||||
We could fix this either using a Kconfig dependency on CONFIG_OF
|
||||
or making the one line conditional. The latter gives us better
|
||||
compile test coverage, so this is what I'm doing here.
|
||||
|
||||
Fixes: 69497eb9234e ("drm: bridge: dw-hdmi: Implement DRM bridge registration")
|
||||
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170123122312.3290934-1-arnd@arndb.de
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 4fda071..9a9ec27 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -2060,7 +2060,9 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
|
||||
|
||||
hdmi->bridge.driver_private = hdmi;
|
||||
hdmi->bridge.funcs = &dw_hdmi_bridge_funcs;
|
||||
+#ifdef CONFIG_OF
|
||||
hdmi->bridge.of_node = pdev->dev.of_node;
|
||||
+#endif
|
||||
|
||||
ret = dw_hdmi_fb_registered(hdmi);
|
||||
if (ret)
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
From 1ab78b07672b5e80bff302b1f2fab863a3107f2e Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Fri, 3 Mar 2017 19:19:58 +0200
|
||||
Subject: [PATCH 31/93] drm: bridge: dw-hdmi: Remove unused functions
|
||||
|
||||
Most of the hdmi_phy_test_*() functions are unused. Remove them.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Tested-by: Nickey Yang <nickey.yang@rock-chips.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170303172007.26541-2-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 26 --------------------------
|
||||
1 file changed, 26 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 9a9ec27..ce74963 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -837,32 +837,6 @@ static inline void hdmi_phy_test_clear(struct dw_hdmi *hdmi,
|
||||
HDMI_PHY_TST0_TSTCLR_MASK, HDMI_PHY_TST0);
|
||||
}
|
||||
|
||||
-static inline void hdmi_phy_test_enable(struct dw_hdmi *hdmi,
|
||||
- unsigned char bit)
|
||||
-{
|
||||
- hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTEN_OFFSET,
|
||||
- HDMI_PHY_TST0_TSTEN_MASK, HDMI_PHY_TST0);
|
||||
-}
|
||||
-
|
||||
-static inline void hdmi_phy_test_clock(struct dw_hdmi *hdmi,
|
||||
- unsigned char bit)
|
||||
-{
|
||||
- hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLK_OFFSET,
|
||||
- HDMI_PHY_TST0_TSTCLK_MASK, HDMI_PHY_TST0);
|
||||
-}
|
||||
-
|
||||
-static inline void hdmi_phy_test_din(struct dw_hdmi *hdmi,
|
||||
- unsigned char bit)
|
||||
-{
|
||||
- hdmi_writeb(hdmi, bit, HDMI_PHY_TST1);
|
||||
-}
|
||||
-
|
||||
-static inline void hdmi_phy_test_dout(struct dw_hdmi *hdmi,
|
||||
- unsigned char bit)
|
||||
-{
|
||||
- hdmi_writeb(hdmi, bit, HDMI_PHY_TST2);
|
||||
-}
|
||||
-
|
||||
static bool hdmi_phy_wait_i2c_done(struct dw_hdmi *hdmi, int msec)
|
||||
{
|
||||
u32 val;
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
From 83ea2ac12ecbd8d77aa2ac7c3effcdac8301ef26 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Fri, 3 Mar 2017 19:19:59 +0200
|
||||
Subject: [PATCH 32/93] drm: bridge: dw-hdmi: Move CSC configuration out of PHY
|
||||
code
|
||||
|
||||
The color space converter isn't part of the PHY, move its configuration
|
||||
out of PHY code.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170303172007.26541-3-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 25 ++++++++++---------------
|
||||
1 file changed, 10 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index ce74963..906583b 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -914,7 +914,7 @@ static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable)
|
||||
HDMI_PHY_CONF0_SELDIPIF_MASK);
|
||||
}
|
||||
|
||||
-static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon)
|
||||
+static int hdmi_phy_configure(struct dw_hdmi *hdmi)
|
||||
{
|
||||
u8 val, msec;
|
||||
const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
|
||||
@@ -946,14 +946,6 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- /* Enable csc path */
|
||||
- if (cscon)
|
||||
- val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH;
|
||||
- else
|
||||
- val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS;
|
||||
-
|
||||
- hdmi_writeb(hdmi, val, HDMI_MC_FLOWCTRL);
|
||||
-
|
||||
/* gen2 tx power off */
|
||||
dw_hdmi_phy_gen2_txpwron(hdmi, 0);
|
||||
|
||||
@@ -1028,10 +1020,6 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon)
|
||||
static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
|
||||
{
|
||||
int i, ret;
|
||||
- bool cscon;
|
||||
-
|
||||
- /*check csc whether needed activated in HDMI mode */
|
||||
- cscon = hdmi->sink_is_hdmi && is_color_space_conversion(hdmi);
|
||||
|
||||
/* HDMI Phy spec says to do the phy initialization sequence twice */
|
||||
for (i = 0; i < 2; i++) {
|
||||
@@ -1040,8 +1028,7 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
|
||||
dw_hdmi_phy_enable_tmds(hdmi, 0);
|
||||
dw_hdmi_phy_enable_powerdown(hdmi, true);
|
||||
|
||||
- /* Enable CSC */
|
||||
- ret = hdmi_phy_configure(hdmi, cscon);
|
||||
+ ret = hdmi_phy_configure(hdmi);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
@@ -1303,6 +1290,14 @@ static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi)
|
||||
clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE;
|
||||
hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
|
||||
}
|
||||
+
|
||||
+ /* Enable color space conversion if needed (for HDMI sinks only). */
|
||||
+ if (hdmi->sink_is_hdmi && is_color_space_conversion(hdmi))
|
||||
+ hdmi_writeb(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH,
|
||||
+ HDMI_MC_FLOWCTRL);
|
||||
+ else
|
||||
+ hdmi_writeb(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS,
|
||||
+ HDMI_MC_FLOWCTRL);
|
||||
}
|
||||
|
||||
static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi)
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
From 63411a28c0aad6f7df41c8d835d479d45ca35101 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Fri, 3 Mar 2017 19:20:00 +0200
|
||||
Subject: [PATCH 33/93] drm: bridge: dw-hdmi: Enable CSC even for DVI
|
||||
|
||||
If the input pixel format is not RGB, the CSC must be enabled in order to
|
||||
provide valid pixel to DVI sinks.
|
||||
This patch removes the hdmi only dependency on the CSC enabling.
|
||||
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170303172007.26541-4-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 906583b..d863b33 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -1291,8 +1291,8 @@ static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi)
|
||||
hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
|
||||
}
|
||||
|
||||
- /* Enable color space conversion if needed (for HDMI sinks only). */
|
||||
- if (hdmi->sink_is_hdmi && is_color_space_conversion(hdmi))
|
||||
+ /* Enable color space conversion if needed */
|
||||
+ if (is_color_space_conversion(hdmi))
|
||||
hdmi_writeb(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH,
|
||||
HDMI_MC_FLOWCTRL);
|
||||
else
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
From 4910824c44da97e1e8f1b934e75d0d40aaabaddc Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Mon, 6 Mar 2017 01:35:39 +0200
|
||||
Subject: [PATCH 34/93] drm: bridge: dw-hdmi: Fix the PHY power down sequence
|
||||
|
||||
The PHY requires us to wait for the PHY to switch to low power mode
|
||||
after deasserting TXPWRON and before asserting PDDQ in the power down
|
||||
sequence, otherwise power down will fail.
|
||||
|
||||
The PHY power down can be monitored though the TX_READY bit, available
|
||||
through I2C in the PHY registers, or the TX_PHY_LOCK bit, available
|
||||
through the HDMI TX registers. As the two are equivalent, let's pick the
|
||||
easier solution of polling the TX_PHY_LOCK bit.
|
||||
|
||||
The power down code is currently duplicated in multiple places. To avoid
|
||||
spreading multiple calls to a TX_PHY_LOCK poll function, we have to
|
||||
refactor the power down code and group it all in a single function.
|
||||
|
||||
Tests showed that one poll iteration was enough for TX_PHY_LOCK to
|
||||
become low, without requiring any additional delay. Retrying the read
|
||||
five times with a 1ms to 2ms delay between each attempt should thus be
|
||||
more than enough.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170305233539.11898-1-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 52 +++++++++++++++++++++++++++++++++-------
|
||||
1 file changed, 43 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index d863b33..3a1cd4c 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -116,6 +116,7 @@ struct dw_hdmi_i2c {
|
||||
struct dw_hdmi_phy_data {
|
||||
enum dw_hdmi_phy_type type;
|
||||
const char *name;
|
||||
+ unsigned int gen;
|
||||
bool has_svsret;
|
||||
};
|
||||
|
||||
@@ -914,6 +915,40 @@ static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable)
|
||||
HDMI_PHY_CONF0_SELDIPIF_MASK);
|
||||
}
|
||||
|
||||
+static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi)
|
||||
+{
|
||||
+ const struct dw_hdmi_phy_data *phy = hdmi->phy;
|
||||
+ unsigned int i;
|
||||
+ u16 val;
|
||||
+
|
||||
+ if (phy->gen == 1) {
|
||||
+ dw_hdmi_phy_enable_tmds(hdmi, 0);
|
||||
+ dw_hdmi_phy_enable_powerdown(hdmi, true);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ dw_hdmi_phy_gen2_txpwron(hdmi, 0);
|
||||
+
|
||||
+ /*
|
||||
+ * Wait for TX_PHY_LOCK to be deasserted to indicate that the PHY went
|
||||
+ * to low power mode.
|
||||
+ */
|
||||
+ for (i = 0; i < 5; ++i) {
|
||||
+ val = hdmi_readb(hdmi, HDMI_PHY_STAT0);
|
||||
+ if (!(val & HDMI_PHY_TX_PHY_LOCK))
|
||||
+ break;
|
||||
+
|
||||
+ usleep_range(1000, 2000);
|
||||
+ }
|
||||
+
|
||||
+ if (val & HDMI_PHY_TX_PHY_LOCK)
|
||||
+ dev_warn(hdmi->dev, "PHY failed to power down\n");
|
||||
+ else
|
||||
+ dev_dbg(hdmi->dev, "PHY powered down in %u iterations\n", i);
|
||||
+
|
||||
+ dw_hdmi_phy_gen2_pddq(hdmi, 1);
|
||||
+}
|
||||
+
|
||||
static int hdmi_phy_configure(struct dw_hdmi *hdmi)
|
||||
{
|
||||
u8 val, msec;
|
||||
@@ -946,11 +981,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- /* gen2 tx power off */
|
||||
- dw_hdmi_phy_gen2_txpwron(hdmi, 0);
|
||||
-
|
||||
- /* gen2 pddq */
|
||||
- dw_hdmi_phy_gen2_pddq(hdmi, 1);
|
||||
+ dw_hdmi_phy_power_off(hdmi);
|
||||
|
||||
/* Leave low power consumption mode by asserting SVSRET. */
|
||||
if (hdmi->phy->has_svsret)
|
||||
@@ -1025,8 +1056,6 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
|
||||
for (i = 0; i < 2; i++) {
|
||||
dw_hdmi_phy_sel_data_en_pol(hdmi, 1);
|
||||
dw_hdmi_phy_sel_interface_control(hdmi, 0);
|
||||
- dw_hdmi_phy_enable_tmds(hdmi, 0);
|
||||
- dw_hdmi_phy_enable_powerdown(hdmi, true);
|
||||
|
||||
ret = hdmi_phy_configure(hdmi);
|
||||
if (ret)
|
||||
@@ -1256,8 +1285,7 @@ static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi)
|
||||
if (!hdmi->phy_enabled)
|
||||
return;
|
||||
|
||||
- dw_hdmi_phy_enable_tmds(hdmi, 0);
|
||||
- dw_hdmi_phy_enable_powerdown(hdmi, true);
|
||||
+ dw_hdmi_phy_power_off(hdmi);
|
||||
|
||||
hdmi->phy_enabled = false;
|
||||
}
|
||||
@@ -1827,23 +1855,29 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
{
|
||||
.type = DW_HDMI_PHY_DWC_HDMI_TX_PHY,
|
||||
.name = "DWC HDMI TX PHY",
|
||||
+ .gen = 1,
|
||||
}, {
|
||||
.type = DW_HDMI_PHY_DWC_MHL_PHY_HEAC,
|
||||
.name = "DWC MHL PHY + HEAC PHY",
|
||||
+ .gen = 2,
|
||||
.has_svsret = true,
|
||||
}, {
|
||||
.type = DW_HDMI_PHY_DWC_MHL_PHY,
|
||||
.name = "DWC MHL PHY",
|
||||
+ .gen = 2,
|
||||
.has_svsret = true,
|
||||
}, {
|
||||
.type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY_HEAC,
|
||||
.name = "DWC HDMI 3D TX PHY + HEAC PHY",
|
||||
+ .gen = 2,
|
||||
}, {
|
||||
.type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY,
|
||||
.name = "DWC HDMI 3D TX PHY",
|
||||
+ .gen = 2,
|
||||
}, {
|
||||
.type = DW_HDMI_PHY_DWC_HDMI20_TX_PHY,
|
||||
.name = "DWC HDMI 2.0 TX PHY",
|
||||
+ .gen = 2,
|
||||
.has_svsret = true,
|
||||
}
|
||||
};
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
From be5d590fc7021d9fa4aa9acd528f72047e8fd82b Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Mon, 6 Mar 2017 01:35:57 +0200
|
||||
Subject: [PATCH 35/93] drm: bridge: dw-hdmi: Fix the PHY power up sequence
|
||||
|
||||
When powering the PHY up we need to wait for the PLL to lock. This is
|
||||
done by polling the TX_PHY_LOCK bit in the HDMI_PHY_STAT0 register
|
||||
(interrupt-based wait could be implemented as well but is likely
|
||||
overkill). The bit is asserted when the PLL locks, but the current code
|
||||
incorrectly waits for the bit to be deasserted. Fix it, and while at it,
|
||||
replace the udelay() with a sleep as the code never runs in
|
||||
non-sleepable context.
|
||||
|
||||
To be consistent with the power down implementation move the poll loop
|
||||
to the power off function.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170305233557.11945-1-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 65 +++++++++++++++++++++++-----------------
|
||||
1 file changed, 37 insertions(+), 28 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 3a1cd4c..c25eac8 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -949,9 +949,44 @@ static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi)
|
||||
dw_hdmi_phy_gen2_pddq(hdmi, 1);
|
||||
}
|
||||
|
||||
+static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi)
|
||||
+{
|
||||
+ const struct dw_hdmi_phy_data *phy = hdmi->phy;
|
||||
+ unsigned int i;
|
||||
+ u8 val;
|
||||
+
|
||||
+ if (phy->gen == 1) {
|
||||
+ dw_hdmi_phy_enable_powerdown(hdmi, false);
|
||||
+
|
||||
+ /* Toggle TMDS enable. */
|
||||
+ dw_hdmi_phy_enable_tmds(hdmi, 0);
|
||||
+ dw_hdmi_phy_enable_tmds(hdmi, 1);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ dw_hdmi_phy_gen2_txpwron(hdmi, 1);
|
||||
+ dw_hdmi_phy_gen2_pddq(hdmi, 0);
|
||||
+
|
||||
+ /* Wait for PHY PLL lock */
|
||||
+ for (i = 0; i < 5; ++i) {
|
||||
+ val = hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
|
||||
+ if (val)
|
||||
+ break;
|
||||
+
|
||||
+ usleep_range(1000, 2000);
|
||||
+ }
|
||||
+
|
||||
+ if (!val) {
|
||||
+ dev_err(hdmi->dev, "PHY PLL failed to lock\n");
|
||||
+ return -ETIMEDOUT;
|
||||
+ }
|
||||
+
|
||||
+ dev_dbg(hdmi->dev, "PHY PLL locked %u iterations\n", i);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int hdmi_phy_configure(struct dw_hdmi *hdmi)
|
||||
{
|
||||
- u8 val, msec;
|
||||
const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
|
||||
const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg;
|
||||
const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
|
||||
@@ -1019,33 +1054,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
|
||||
hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE,
|
||||
HDMI_3D_TX_PHY_CKCALCTRL);
|
||||
|
||||
- dw_hdmi_phy_enable_powerdown(hdmi, false);
|
||||
-
|
||||
- /* toggle TMDS enable */
|
||||
- dw_hdmi_phy_enable_tmds(hdmi, 0);
|
||||
- dw_hdmi_phy_enable_tmds(hdmi, 1);
|
||||
-
|
||||
- /* gen2 tx power on */
|
||||
- dw_hdmi_phy_gen2_txpwron(hdmi, 1);
|
||||
- dw_hdmi_phy_gen2_pddq(hdmi, 0);
|
||||
-
|
||||
- /* Wait for PHY PLL lock */
|
||||
- msec = 5;
|
||||
- do {
|
||||
- val = hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
|
||||
- if (!val)
|
||||
- break;
|
||||
-
|
||||
- if (msec == 0) {
|
||||
- dev_err(hdmi->dev, "PHY PLL not locked\n");
|
||||
- return -ETIMEDOUT;
|
||||
- }
|
||||
-
|
||||
- udelay(1000);
|
||||
- msec--;
|
||||
- } while (1);
|
||||
-
|
||||
- return 0;
|
||||
+ return dw_hdmi_phy_power_on(hdmi);
|
||||
}
|
||||
|
||||
static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,268 @@
|
|||
From 815a37cd2514fc9fac5913bdefad6fcbff35d743 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Mon, 6 Mar 2017 01:36:15 +0200
|
||||
Subject: [PATCH 36/93] drm: bridge: dw-hdmi: Create PHY operations
|
||||
|
||||
The HDMI TX controller support different PHYs whose programming
|
||||
interface can vary significantly, especially with vendor PHYs that are
|
||||
not provided by Synopsys. To support them, create a PHY operation
|
||||
structure that can be provided by the platform glue layer. The existing
|
||||
PHY handling code (limited to Synopsys PHY support) is refactored into a
|
||||
set of default PHY operations that are used automatically when the
|
||||
platform glue doesn't provide its own operations.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170305233615.11993-1-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 95 ++++++++++++++++++++++++++++------------
|
||||
include/drm/bridge/dw_hdmi.h | 18 +++++++-
|
||||
2 files changed, 82 insertions(+), 31 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index c25eac8..cb27038 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -141,8 +141,12 @@ struct dw_hdmi {
|
||||
u8 edid[HDMI_EDID_LEN];
|
||||
bool cable_plugin;
|
||||
|
||||
- const struct dw_hdmi_phy_data *phy;
|
||||
- bool phy_enabled;
|
||||
+ struct {
|
||||
+ const struct dw_hdmi_phy_ops *ops;
|
||||
+ const char *name;
|
||||
+ void *data;
|
||||
+ bool enabled;
|
||||
+ } phy;
|
||||
|
||||
struct drm_display_mode previous_mode;
|
||||
|
||||
@@ -831,6 +835,10 @@ static void hdmi_video_packetize(struct dw_hdmi *hdmi)
|
||||
HDMI_VP_CONF);
|
||||
}
|
||||
|
||||
+/* -----------------------------------------------------------------------------
|
||||
+ * Synopsys PHY Handling
|
||||
+ */
|
||||
+
|
||||
static inline void hdmi_phy_test_clear(struct dw_hdmi *hdmi,
|
||||
unsigned char bit)
|
||||
{
|
||||
@@ -917,7 +925,7 @@ static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable)
|
||||
|
||||
static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi)
|
||||
{
|
||||
- const struct dw_hdmi_phy_data *phy = hdmi->phy;
|
||||
+ const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
|
||||
unsigned int i;
|
||||
u16 val;
|
||||
|
||||
@@ -951,7 +959,7 @@ static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi)
|
||||
|
||||
static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi)
|
||||
{
|
||||
- const struct dw_hdmi_phy_data *phy = hdmi->phy;
|
||||
+ const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
|
||||
unsigned int i;
|
||||
u8 val;
|
||||
|
||||
@@ -987,6 +995,7 @@ static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi)
|
||||
|
||||
static int hdmi_phy_configure(struct dw_hdmi *hdmi)
|
||||
{
|
||||
+ const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
|
||||
const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
|
||||
const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg;
|
||||
const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
|
||||
@@ -1019,7 +1028,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
|
||||
dw_hdmi_phy_power_off(hdmi);
|
||||
|
||||
/* Leave low power consumption mode by asserting SVSRET. */
|
||||
- if (hdmi->phy->has_svsret)
|
||||
+ if (phy->has_svsret)
|
||||
dw_hdmi_phy_enable_svsret(hdmi, 1);
|
||||
|
||||
/* PHY reset. The reset signal is active high on Gen2 PHYs. */
|
||||
@@ -1057,7 +1066,8 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
|
||||
return dw_hdmi_phy_power_on(hdmi);
|
||||
}
|
||||
|
||||
-static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
|
||||
+static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
|
||||
+ struct drm_display_mode *mode)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
@@ -1071,10 +1081,31 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
|
||||
return ret;
|
||||
}
|
||||
|
||||
- hdmi->phy_enabled = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi, void *data)
|
||||
+{
|
||||
+ dw_hdmi_phy_power_off(hdmi);
|
||||
+}
|
||||
+
|
||||
+static enum drm_connector_status dw_hdmi_phy_read_hpd(struct dw_hdmi *hdmi,
|
||||
+ void *data)
|
||||
+{
|
||||
+ return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ?
|
||||
+ connector_status_connected : connector_status_disconnected;
|
||||
+}
|
||||
+
|
||||
+static const struct dw_hdmi_phy_ops dw_hdmi_synopsys_phy_ops = {
|
||||
+ .init = dw_hdmi_phy_init,
|
||||
+ .disable = dw_hdmi_phy_disable,
|
||||
+ .read_hpd = dw_hdmi_phy_read_hpd,
|
||||
+};
|
||||
+
|
||||
+/* -----------------------------------------------------------------------------
|
||||
+ * HDMI TX Setup
|
||||
+ */
|
||||
+
|
||||
static void hdmi_tx_hdcp_config(struct dw_hdmi *hdmi)
|
||||
{
|
||||
u8 de;
|
||||
@@ -1289,16 +1320,6 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
|
||||
hdmi_writeb(hdmi, vsync_len, HDMI_FC_VSYNCINWIDTH);
|
||||
}
|
||||
|
||||
-static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi)
|
||||
-{
|
||||
- if (!hdmi->phy_enabled)
|
||||
- return;
|
||||
-
|
||||
- dw_hdmi_phy_power_off(hdmi);
|
||||
-
|
||||
- hdmi->phy_enabled = false;
|
||||
-}
|
||||
-
|
||||
/* HDMI Initialization Step B.4 */
|
||||
static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi)
|
||||
{
|
||||
@@ -1431,9 +1452,10 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
|
||||
hdmi_av_composer(hdmi, mode);
|
||||
|
||||
/* HDMI Initializateion Step B.2 */
|
||||
- ret = dw_hdmi_phy_init(hdmi);
|
||||
+ ret = hdmi->phy.ops->init(hdmi, hdmi->phy.data, &hdmi->previous_mode);
|
||||
if (ret)
|
||||
return ret;
|
||||
+ hdmi->phy.enabled = true;
|
||||
|
||||
/* HDMI Initialization Step B.3 */
|
||||
dw_hdmi_enable_video_path(hdmi);
|
||||
@@ -1548,7 +1570,11 @@ static void dw_hdmi_poweron(struct dw_hdmi *hdmi)
|
||||
|
||||
static void dw_hdmi_poweroff(struct dw_hdmi *hdmi)
|
||||
{
|
||||
- dw_hdmi_phy_disable(hdmi);
|
||||
+ if (hdmi->phy.enabled) {
|
||||
+ hdmi->phy.ops->disable(hdmi, hdmi->phy.data);
|
||||
+ hdmi->phy.enabled = false;
|
||||
+ }
|
||||
+
|
||||
hdmi->bridge_is_on = false;
|
||||
}
|
||||
|
||||
@@ -1611,8 +1637,7 @@ static void dw_hdmi_update_phy_mask(struct dw_hdmi *hdmi)
|
||||
dw_hdmi_update_phy_mask(hdmi);
|
||||
mutex_unlock(&hdmi->mutex);
|
||||
|
||||
- return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ?
|
||||
- connector_status_connected : connector_status_disconnected;
|
||||
+ return hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
|
||||
}
|
||||
|
||||
static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
|
||||
@@ -1898,19 +1923,31 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
|
||||
|
||||
phy_type = hdmi_readb(hdmi, HDMI_CONFIG2_ID);
|
||||
|
||||
+ if (phy_type == DW_HDMI_PHY_VENDOR_PHY) {
|
||||
+ /* Vendor PHYs require support from the glue layer. */
|
||||
+ if (!hdmi->plat_data->phy_ops || !hdmi->plat_data->phy_name) {
|
||||
+ dev_err(hdmi->dev,
|
||||
+ "Vendor HDMI PHY not supported by glue layer\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ hdmi->phy.ops = hdmi->plat_data->phy_ops;
|
||||
+ hdmi->phy.data = hdmi->plat_data->phy_data;
|
||||
+ hdmi->phy.name = hdmi->plat_data->phy_name;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ /* Synopsys PHYs are handled internally. */
|
||||
for (i = 0; i < ARRAY_SIZE(dw_hdmi_phys); ++i) {
|
||||
if (dw_hdmi_phys[i].type == phy_type) {
|
||||
- hdmi->phy = &dw_hdmi_phys[i];
|
||||
+ hdmi->phy.ops = &dw_hdmi_synopsys_phy_ops;
|
||||
+ hdmi->phy.name = dw_hdmi_phys[i].name;
|
||||
+ hdmi->phy.data = (void *)&dw_hdmi_phys[i];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
- if (phy_type == DW_HDMI_PHY_VENDOR_PHY)
|
||||
- dev_err(hdmi->dev, "Unsupported vendor HDMI PHY\n");
|
||||
- else
|
||||
- dev_err(hdmi->dev, "Unsupported HDMI PHY type (%02x)\n",
|
||||
- phy_type);
|
||||
-
|
||||
+ dev_err(hdmi->dev, "Unsupported HDMI PHY type (%02x)\n", phy_type);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@@ -2031,7 +2068,7 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
|
||||
dev_info(dev, "Detected HDMI TX controller v%x.%03x %s HDCP (%s)\n",
|
||||
hdmi->version >> 12, hdmi->version & 0xfff,
|
||||
prod_id1 & HDMI_PRODUCT_ID1_HDCP ? "with" : "without",
|
||||
- hdmi->phy->name);
|
||||
+ hdmi->phy.name);
|
||||
|
||||
initialize_hdmi_ih_mutes(hdmi);
|
||||
|
||||
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
|
||||
index b080a17..0f583ca 100644
|
||||
--- a/include/drm/bridge/dw_hdmi.h
|
||||
+++ b/include/drm/bridge/dw_hdmi.h
|
||||
@@ -57,13 +57,27 @@ struct dw_hdmi_phy_config {
|
||||
u16 vlev_ctr; /* voltage level control */
|
||||
};
|
||||
|
||||
+struct dw_hdmi_phy_ops {
|
||||
+ int (*init)(struct dw_hdmi *hdmi, void *data,
|
||||
+ struct drm_display_mode *mode);
|
||||
+ void (*disable)(struct dw_hdmi *hdmi, void *data);
|
||||
+ enum drm_connector_status (*read_hpd)(struct dw_hdmi *hdmi, void *data);
|
||||
+};
|
||||
+
|
||||
struct dw_hdmi_plat_data {
|
||||
enum dw_hdmi_devtype dev_type;
|
||||
+ enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
|
||||
+ struct drm_display_mode *mode);
|
||||
+
|
||||
+ /* Vendor PHY support */
|
||||
+ const struct dw_hdmi_phy_ops *phy_ops;
|
||||
+ const char *phy_name;
|
||||
+ void *phy_data;
|
||||
+
|
||||
+ /* Synopsys PHY support */
|
||||
const struct dw_hdmi_mpll_config *mpll_cfg;
|
||||
const struct dw_hdmi_curr_ctrl *cur_ctr;
|
||||
const struct dw_hdmi_phy_config *phy_config;
|
||||
- enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
|
||||
- struct drm_display_mode *mode);
|
||||
};
|
||||
|
||||
int dw_hdmi_probe(struct platform_device *pdev,
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,251 @@
|
|||
From 3fdd6b3e658373e45ecbe36093403a30bd309df5 Mon Sep 17 00:00:00 2001
|
||||
From: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
|
||||
Date: Fri, 3 Mar 2017 19:20:04 +0200
|
||||
Subject: [PATCH 37/93] drm: bridge: dw-hdmi: Add support for custom PHY
|
||||
configuration
|
||||
|
||||
The DWC HDMI TX controller interfaces with a companion PHY. While
|
||||
Synopsys provides multiple standard PHYs, SoC vendors can also integrate
|
||||
a custom PHY.
|
||||
|
||||
Modularize PHY configuration to support vendor PHYs through platform
|
||||
data. The existing PHY configuration code was originally written to
|
||||
support the DWC HDMI 3D TX PHY, and seems to be compatible with the DWC
|
||||
MLP PHY. The HDMI 2.0 PHY will require a separate configuration
|
||||
function.
|
||||
|
||||
Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Reviewed-by: Jose Abreu <Jose.Abreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170303172007.26541-8-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 109 ++++++++++++++++++++++++++-------------
|
||||
include/drm/bridge/dw_hdmi.h | 7 +++
|
||||
2 files changed, 81 insertions(+), 35 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index cb27038..b835d81 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -118,6 +118,9 @@ struct dw_hdmi_phy_data {
|
||||
const char *name;
|
||||
unsigned int gen;
|
||||
bool has_svsret;
|
||||
+ int (*configure)(struct dw_hdmi *hdmi,
|
||||
+ const struct dw_hdmi_plat_data *pdata,
|
||||
+ unsigned long mpixelclock);
|
||||
};
|
||||
|
||||
struct dw_hdmi {
|
||||
@@ -860,8 +863,8 @@ static bool hdmi_phy_wait_i2c_done(struct dw_hdmi *hdmi, int msec)
|
||||
return true;
|
||||
}
|
||||
|
||||
-static void hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
|
||||
- unsigned char addr)
|
||||
+void dw_hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
|
||||
+ unsigned char addr)
|
||||
{
|
||||
hdmi_writeb(hdmi, 0xFF, HDMI_IH_I2CMPHY_STAT0);
|
||||
hdmi_writeb(hdmi, addr, HDMI_PHY_I2CM_ADDRESS_ADDR);
|
||||
@@ -873,6 +876,7 @@ static void hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
|
||||
HDMI_PHY_I2CM_OPERATION_ADDR);
|
||||
hdmi_phy_wait_i2c_done(hdmi, 1000);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(dw_hdmi_phy_i2c_write);
|
||||
|
||||
static void dw_hdmi_phy_enable_powerdown(struct dw_hdmi *hdmi, bool enable)
|
||||
{
|
||||
@@ -993,37 +997,67 @@ static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int hdmi_phy_configure(struct dw_hdmi *hdmi)
|
||||
+/*
|
||||
+ * PHY configuration function for the DWC HDMI 3D TX PHY. Based on the available
|
||||
+ * information the DWC MHL PHY has the same register layout and is thus also
|
||||
+ * supported by this function.
|
||||
+ */
|
||||
+static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi,
|
||||
+ const struct dw_hdmi_plat_data *pdata,
|
||||
+ unsigned long mpixelclock)
|
||||
{
|
||||
- const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
|
||||
- const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
|
||||
const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg;
|
||||
const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
|
||||
const struct dw_hdmi_phy_config *phy_config = pdata->phy_config;
|
||||
|
||||
/* PLL/MPLL Cfg - always match on final entry */
|
||||
for (; mpll_config->mpixelclock != ~0UL; mpll_config++)
|
||||
- if (hdmi->hdmi_data.video_mode.mpixelclock <=
|
||||
- mpll_config->mpixelclock)
|
||||
+ if (mpixelclock <= mpll_config->mpixelclock)
|
||||
break;
|
||||
|
||||
for (; curr_ctrl->mpixelclock != ~0UL; curr_ctrl++)
|
||||
- if (hdmi->hdmi_data.video_mode.mpixelclock <=
|
||||
- curr_ctrl->mpixelclock)
|
||||
+ if (mpixelclock <= curr_ctrl->mpixelclock)
|
||||
break;
|
||||
|
||||
for (; phy_config->mpixelclock != ~0UL; phy_config++)
|
||||
- if (hdmi->hdmi_data.video_mode.mpixelclock <=
|
||||
- phy_config->mpixelclock)
|
||||
+ if (mpixelclock <= phy_config->mpixelclock)
|
||||
break;
|
||||
|
||||
if (mpll_config->mpixelclock == ~0UL ||
|
||||
curr_ctrl->mpixelclock == ~0UL ||
|
||||
- phy_config->mpixelclock == ~0UL) {
|
||||
- dev_err(hdmi->dev, "Pixel clock %d - unsupported by HDMI\n",
|
||||
- hdmi->hdmi_data.video_mode.mpixelclock);
|
||||
+ phy_config->mpixelclock == ~0UL)
|
||||
return -EINVAL;
|
||||
- }
|
||||
+
|
||||
+ dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce,
|
||||
+ HDMI_3D_TX_PHY_CPCE_CTRL);
|
||||
+ dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp,
|
||||
+ HDMI_3D_TX_PHY_GMPCTRL);
|
||||
+ dw_hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0],
|
||||
+ HDMI_3D_TX_PHY_CURRCTRL);
|
||||
+
|
||||
+ dw_hdmi_phy_i2c_write(hdmi, 0, HDMI_3D_TX_PHY_PLLPHBYCTRL);
|
||||
+ dw_hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_FB_CLK,
|
||||
+ HDMI_3D_TX_PHY_MSM_CTRL);
|
||||
+
|
||||
+ dw_hdmi_phy_i2c_write(hdmi, phy_config->term, HDMI_3D_TX_PHY_TXTERM);
|
||||
+ dw_hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr,
|
||||
+ HDMI_3D_TX_PHY_CKSYMTXCTRL);
|
||||
+ dw_hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr,
|
||||
+ HDMI_3D_TX_PHY_VLEVCTRL);
|
||||
+
|
||||
+ /* Override and disable clock termination. */
|
||||
+ dw_hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE,
|
||||
+ HDMI_3D_TX_PHY_CKCALCTRL);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int hdmi_phy_configure(struct dw_hdmi *hdmi)
|
||||
+{
|
||||
+ const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
|
||||
+ const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
|
||||
+ unsigned long mpixelclock = hdmi->hdmi_data.video_mode.mpixelclock;
|
||||
+ int ret;
|
||||
|
||||
dw_hdmi_phy_power_off(hdmi);
|
||||
|
||||
@@ -1042,26 +1076,16 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
|
||||
HDMI_PHY_I2CM_SLAVE_ADDR);
|
||||
hdmi_phy_test_clear(hdmi, 0);
|
||||
|
||||
- hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce,
|
||||
- HDMI_3D_TX_PHY_CPCE_CTRL);
|
||||
- hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp,
|
||||
- HDMI_3D_TX_PHY_GMPCTRL);
|
||||
- hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0],
|
||||
- HDMI_3D_TX_PHY_CURRCTRL);
|
||||
-
|
||||
- hdmi_phy_i2c_write(hdmi, 0, HDMI_3D_TX_PHY_PLLPHBYCTRL);
|
||||
- hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_FB_CLK,
|
||||
- HDMI_3D_TX_PHY_MSM_CTRL);
|
||||
-
|
||||
- hdmi_phy_i2c_write(hdmi, phy_config->term, HDMI_3D_TX_PHY_TXTERM);
|
||||
- hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr,
|
||||
- HDMI_3D_TX_PHY_CKSYMTXCTRL);
|
||||
- hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr,
|
||||
- HDMI_3D_TX_PHY_VLEVCTRL);
|
||||
-
|
||||
- /* Override and disable clock termination. */
|
||||
- hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE,
|
||||
- HDMI_3D_TX_PHY_CKCALCTRL);
|
||||
+ /* Write to the PHY as configured by the platform */
|
||||
+ if (pdata->configure_phy)
|
||||
+ ret = pdata->configure_phy(hdmi, pdata, mpixelclock);
|
||||
+ else
|
||||
+ ret = phy->configure(hdmi, pdata, mpixelclock);
|
||||
+ if (ret) {
|
||||
+ dev_err(hdmi->dev, "PHY configuration failed (clock %lu)\n",
|
||||
+ mpixelclock);
|
||||
+ return ret;
|
||||
+ }
|
||||
|
||||
return dw_hdmi_phy_power_on(hdmi);
|
||||
}
|
||||
@@ -1895,24 +1919,31 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
.name = "DWC MHL PHY + HEAC PHY",
|
||||
.gen = 2,
|
||||
.has_svsret = true,
|
||||
+ .configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
|
||||
}, {
|
||||
.type = DW_HDMI_PHY_DWC_MHL_PHY,
|
||||
.name = "DWC MHL PHY",
|
||||
.gen = 2,
|
||||
.has_svsret = true,
|
||||
+ .configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
|
||||
}, {
|
||||
.type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY_HEAC,
|
||||
.name = "DWC HDMI 3D TX PHY + HEAC PHY",
|
||||
.gen = 2,
|
||||
+ .configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
|
||||
}, {
|
||||
.type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY,
|
||||
.name = "DWC HDMI 3D TX PHY",
|
||||
.gen = 2,
|
||||
+ .configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
|
||||
}, {
|
||||
.type = DW_HDMI_PHY_DWC_HDMI20_TX_PHY,
|
||||
.name = "DWC HDMI 2.0 TX PHY",
|
||||
.gen = 2,
|
||||
.has_svsret = true,
|
||||
+ }, {
|
||||
+ .type = DW_HDMI_PHY_VENDOR_PHY,
|
||||
+ .name = "Vendor PHY",
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1943,6 +1974,14 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
|
||||
hdmi->phy.ops = &dw_hdmi_synopsys_phy_ops;
|
||||
hdmi->phy.name = dw_hdmi_phys[i].name;
|
||||
hdmi->phy.data = (void *)&dw_hdmi_phys[i];
|
||||
+
|
||||
+ if (!dw_hdmi_phys[i].configure &&
|
||||
+ !hdmi->plat_data->configure_phy) {
|
||||
+ dev_err(hdmi->dev, "%s requires platform support\n",
|
||||
+ hdmi->phy.name);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
|
||||
index 0f583ca..dd33025 100644
|
||||
--- a/include/drm/bridge/dw_hdmi.h
|
||||
+++ b/include/drm/bridge/dw_hdmi.h
|
||||
@@ -78,6 +78,9 @@ struct dw_hdmi_plat_data {
|
||||
const struct dw_hdmi_mpll_config *mpll_cfg;
|
||||
const struct dw_hdmi_curr_ctrl *cur_ctr;
|
||||
const struct dw_hdmi_phy_config *phy_config;
|
||||
+ int (*configure_phy)(struct dw_hdmi *hdmi,
|
||||
+ const struct dw_hdmi_plat_data *pdata,
|
||||
+ unsigned long mpixelclock);
|
||||
};
|
||||
|
||||
int dw_hdmi_probe(struct platform_device *pdev,
|
||||
@@ -91,4 +94,8 @@ int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
|
||||
void dw_hdmi_audio_enable(struct dw_hdmi *hdmi);
|
||||
void dw_hdmi_audio_disable(struct dw_hdmi *hdmi);
|
||||
|
||||
+/* PHY configuration */
|
||||
+void dw_hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
|
||||
+ unsigned char addr);
|
||||
+
|
||||
#endif /* __IMX_HDMI_H__ */
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
From c5bdf6120fed0d57d7e602abc01f0cbacf275737 Mon Sep 17 00:00:00 2001
|
||||
From: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
|
||||
Date: Fri, 3 Mar 2017 19:20:05 +0200
|
||||
Subject: [PATCH 38/93] drm: bridge: dw-hdmi: Remove device type from platform
|
||||
data
|
||||
|
||||
The device type isn't used anymore now that workarounds and PHY-specific
|
||||
operations are performed based on version information read at runtime.
|
||||
Remove it.
|
||||
|
||||
Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170303172007.26541-9-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 2 --
|
||||
drivers/gpu/drm/imx/dw_hdmi-imx.c | 2 --
|
||||
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 1 -
|
||||
include/drm/bridge/dw_hdmi.h | 7 -------
|
||||
4 files changed, 12 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index b835d81..132c006 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -127,7 +127,6 @@ struct dw_hdmi {
|
||||
struct drm_connector connector;
|
||||
struct drm_bridge bridge;
|
||||
|
||||
- enum dw_hdmi_devtype dev_type;
|
||||
unsigned int version;
|
||||
|
||||
struct platform_device *audio;
|
||||
@@ -2014,7 +2013,6 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
|
||||
|
||||
hdmi->plat_data = plat_data;
|
||||
hdmi->dev = dev;
|
||||
- hdmi->dev_type = plat_data->dev_type;
|
||||
hdmi->sample_rate = 48000;
|
||||
hdmi->disabled = true;
|
||||
hdmi->rxsense = true;
|
||||
diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c
|
||||
index f645275..f039641 100644
|
||||
--- a/drivers/gpu/drm/imx/dw_hdmi-imx.c
|
||||
+++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c
|
||||
@@ -175,7 +175,6 @@ static enum drm_mode_status imx6dl_hdmi_mode_valid(struct drm_connector *con,
|
||||
.mpll_cfg = imx_mpll_cfg,
|
||||
.cur_ctr = imx_cur_ctr,
|
||||
.phy_config = imx_phy_config,
|
||||
- .dev_type = IMX6Q_HDMI,
|
||||
.mode_valid = imx6q_hdmi_mode_valid,
|
||||
};
|
||||
|
||||
@@ -183,7 +182,6 @@ static enum drm_mode_status imx6dl_hdmi_mode_valid(struct drm_connector *con,
|
||||
.mpll_cfg = imx_mpll_cfg,
|
||||
.cur_ctr = imx_cur_ctr,
|
||||
.phy_config = imx_phy_config,
|
||||
- .dev_type = IMX6DL_HDMI,
|
||||
.mode_valid = imx6dl_hdmi_mode_valid,
|
||||
};
|
||||
|
||||
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
|
||||
index a6d4a02..d538274 100644
|
||||
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
|
||||
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
|
||||
@@ -237,7 +237,6 @@ static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder)
|
||||
.mpll_cfg = rockchip_mpll_cfg,
|
||||
.cur_ctr = rockchip_cur_ctr,
|
||||
.phy_config = rockchip_phy_config,
|
||||
- .dev_type = RK3288_HDMI,
|
||||
};
|
||||
|
||||
static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = {
|
||||
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
|
||||
index dd33025..545f04fa 100644
|
||||
--- a/include/drm/bridge/dw_hdmi.h
|
||||
+++ b/include/drm/bridge/dw_hdmi.h
|
||||
@@ -21,12 +21,6 @@ enum {
|
||||
DW_HDMI_RES_MAX,
|
||||
};
|
||||
|
||||
-enum dw_hdmi_devtype {
|
||||
- IMX6Q_HDMI,
|
||||
- IMX6DL_HDMI,
|
||||
- RK3288_HDMI,
|
||||
-};
|
||||
-
|
||||
enum dw_hdmi_phy_type {
|
||||
DW_HDMI_PHY_DWC_HDMI_TX_PHY = 0x00,
|
||||
DW_HDMI_PHY_DWC_MHL_PHY_HEAC = 0xb2,
|
||||
@@ -65,7 +59,6 @@ struct dw_hdmi_phy_ops {
|
||||
};
|
||||
|
||||
struct dw_hdmi_plat_data {
|
||||
- enum dw_hdmi_devtype dev_type;
|
||||
enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode);
|
||||
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,227 @@
|
|||
From bee2b64f57985618a1b824362c427eb469f41e06 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Fri, 3 Mar 2017 19:20:06 +0200
|
||||
Subject: [PATCH 39/93] drm: bridge: dw-hdmi: Switch to regmap for register
|
||||
access
|
||||
|
||||
The Synopsys Designware HDMI TX Controller does not enforce register
|
||||
access on platforms instanciating it. The current driver supports two
|
||||
different types of memory-mapped flat register access, but in order to
|
||||
support the Amlogic Meson SoCs integration, and provide a more generic
|
||||
way to handle all sorts of register mapping, switch the register access
|
||||
to use the regmap infrastructure.
|
||||
|
||||
In the case of registers that are not flat memory-mapped or do not
|
||||
conform to the current driver implementation, a regmap struct can be
|
||||
given in the plat_data and be used at probe or bind.
|
||||
|
||||
Since the AHB audio driver is only available with direct memory access,
|
||||
only allow the I2S audio driver to be registered is directly
|
||||
memory-mapped.
|
||||
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Tested-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Reviewed-by: Jose Abreu <Jose.Abreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170303172007.26541-10-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 109 +++++++++++++++++++++------------------
|
||||
include/drm/bridge/dw_hdmi.h | 1 +
|
||||
2 files changed, 59 insertions(+), 51 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 132c006..026a0dc 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <linux/hdmi.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of_device.h>
|
||||
+#include <linux/regmap.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <drm/drm_of.h>
|
||||
@@ -171,8 +172,8 @@ struct dw_hdmi {
|
||||
unsigned int audio_n;
|
||||
bool audio_enable;
|
||||
|
||||
- void (*write)(struct dw_hdmi *hdmi, u8 val, int offset);
|
||||
- u8 (*read)(struct dw_hdmi *hdmi, int offset);
|
||||
+ unsigned int reg_shift;
|
||||
+ struct regmap *regm;
|
||||
};
|
||||
|
||||
#define HDMI_IH_PHY_STAT0_RX_SENSE \
|
||||
@@ -183,42 +184,23 @@ struct dw_hdmi {
|
||||
(HDMI_PHY_RX_SENSE0 | HDMI_PHY_RX_SENSE1 | \
|
||||
HDMI_PHY_RX_SENSE2 | HDMI_PHY_RX_SENSE3)
|
||||
|
||||
-static void dw_hdmi_writel(struct dw_hdmi *hdmi, u8 val, int offset)
|
||||
-{
|
||||
- writel(val, hdmi->regs + (offset << 2));
|
||||
-}
|
||||
-
|
||||
-static u8 dw_hdmi_readl(struct dw_hdmi *hdmi, int offset)
|
||||
-{
|
||||
- return readl(hdmi->regs + (offset << 2));
|
||||
-}
|
||||
-
|
||||
-static void dw_hdmi_writeb(struct dw_hdmi *hdmi, u8 val, int offset)
|
||||
-{
|
||||
- writeb(val, hdmi->regs + offset);
|
||||
-}
|
||||
-
|
||||
-static u8 dw_hdmi_readb(struct dw_hdmi *hdmi, int offset)
|
||||
-{
|
||||
- return readb(hdmi->regs + offset);
|
||||
-}
|
||||
-
|
||||
static inline void hdmi_writeb(struct dw_hdmi *hdmi, u8 val, int offset)
|
||||
{
|
||||
- hdmi->write(hdmi, val, offset);
|
||||
+ regmap_write(hdmi->regm, offset << hdmi->reg_shift, val);
|
||||
}
|
||||
|
||||
static inline u8 hdmi_readb(struct dw_hdmi *hdmi, int offset)
|
||||
{
|
||||
- return hdmi->read(hdmi, offset);
|
||||
+ unsigned int val = 0;
|
||||
+
|
||||
+ regmap_read(hdmi->regm, offset << hdmi->reg_shift, &val);
|
||||
+
|
||||
+ return val;
|
||||
}
|
||||
|
||||
static void hdmi_modb(struct dw_hdmi *hdmi, u8 data, u8 mask, unsigned reg)
|
||||
{
|
||||
- u8 val = hdmi_readb(hdmi, reg) & ~mask;
|
||||
-
|
||||
- val |= data & mask;
|
||||
- hdmi_writeb(hdmi, val, reg);
|
||||
+ regmap_update_bits(hdmi->regm, reg << hdmi->reg_shift, mask, data);
|
||||
}
|
||||
|
||||
static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg,
|
||||
@@ -1989,6 +1971,20 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
+static const struct regmap_config hdmi_regmap_8bit_config = {
|
||||
+ .reg_bits = 32,
|
||||
+ .val_bits = 8,
|
||||
+ .reg_stride = 1,
|
||||
+ .max_register = HDMI_I2CM_FS_SCL_LCNT_0_ADDR,
|
||||
+};
|
||||
+
|
||||
+static const struct regmap_config hdmi_regmap_32bit_config = {
|
||||
+ .reg_bits = 32,
|
||||
+ .val_bits = 32,
|
||||
+ .reg_stride = 4,
|
||||
+ .max_register = HDMI_I2CM_FS_SCL_LCNT_0_ADDR << 2,
|
||||
+};
|
||||
+
|
||||
static struct dw_hdmi *
|
||||
__dw_hdmi_probe(struct platform_device *pdev,
|
||||
const struct dw_hdmi_plat_data *plat_data)
|
||||
@@ -1998,7 +1994,7 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
|
||||
struct platform_device_info pdevinfo;
|
||||
struct device_node *ddc_node;
|
||||
struct dw_hdmi *hdmi;
|
||||
- struct resource *iores;
|
||||
+ struct resource *iores = NULL;
|
||||
int irq;
|
||||
int ret;
|
||||
u32 val = 1;
|
||||
@@ -2022,22 +2018,6 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
|
||||
mutex_init(&hdmi->audio_mutex);
|
||||
spin_lock_init(&hdmi->audio_lock);
|
||||
|
||||
- of_property_read_u32(np, "reg-io-width", &val);
|
||||
-
|
||||
- switch (val) {
|
||||
- case 4:
|
||||
- hdmi->write = dw_hdmi_writel;
|
||||
- hdmi->read = dw_hdmi_readl;
|
||||
- break;
|
||||
- case 1:
|
||||
- hdmi->write = dw_hdmi_writeb;
|
||||
- hdmi->read = dw_hdmi_readb;
|
||||
- break;
|
||||
- default:
|
||||
- dev_err(dev, "reg-io-width must be 1 or 4\n");
|
||||
- return ERR_PTR(-EINVAL);
|
||||
- }
|
||||
-
|
||||
ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
|
||||
if (ddc_node) {
|
||||
hdmi->ddc = of_get_i2c_adapter_by_node(ddc_node);
|
||||
@@ -2051,11 +2031,38 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
|
||||
dev_dbg(hdmi->dev, "no ddc property found\n");
|
||||
}
|
||||
|
||||
- iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
- hdmi->regs = devm_ioremap_resource(dev, iores);
|
||||
- if (IS_ERR(hdmi->regs)) {
|
||||
- ret = PTR_ERR(hdmi->regs);
|
||||
- goto err_res;
|
||||
+ if (!plat_data->regm) {
|
||||
+ const struct regmap_config *reg_config;
|
||||
+
|
||||
+ of_property_read_u32(np, "reg-io-width", &val);
|
||||
+ switch (val) {
|
||||
+ case 4:
|
||||
+ reg_config = &hdmi_regmap_32bit_config;
|
||||
+ hdmi->reg_shift = 2;
|
||||
+ break;
|
||||
+ case 1:
|
||||
+ reg_config = &hdmi_regmap_8bit_config;
|
||||
+ break;
|
||||
+ default:
|
||||
+ dev_err(dev, "reg-io-width must be 1 or 4\n");
|
||||
+ return ERR_PTR(-EINVAL);
|
||||
+ }
|
||||
+
|
||||
+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
+ hdmi->regs = devm_ioremap_resource(dev, iores);
|
||||
+ if (IS_ERR(hdmi->regs)) {
|
||||
+ ret = PTR_ERR(hdmi->regs);
|
||||
+ goto err_res;
|
||||
+ }
|
||||
+
|
||||
+ hdmi->regm = devm_regmap_init_mmio(dev, hdmi->regs, reg_config);
|
||||
+ if (IS_ERR(hdmi->regm)) {
|
||||
+ dev_err(dev, "Failed to configure regmap\n");
|
||||
+ ret = PTR_ERR(hdmi->regm);
|
||||
+ goto err_res;
|
||||
+ }
|
||||
+ } else {
|
||||
+ hdmi->regm = plat_data->regm;
|
||||
}
|
||||
|
||||
hdmi->isfr_clk = devm_clk_get(hdmi->dev, "isfr");
|
||||
@@ -2165,7 +2172,7 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
|
||||
config0 = hdmi_readb(hdmi, HDMI_CONFIG0_ID);
|
||||
config3 = hdmi_readb(hdmi, HDMI_CONFIG3_ID);
|
||||
|
||||
- if (config3 & HDMI_CONFIG3_AHBAUDDMA) {
|
||||
+ if (iores && config3 & HDMI_CONFIG3_AHBAUDDMA) {
|
||||
struct dw_hdmi_audio_data audio;
|
||||
|
||||
audio.phys = iores->start;
|
||||
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
|
||||
index 545f04fa..bcceee8 100644
|
||||
--- a/include/drm/bridge/dw_hdmi.h
|
||||
+++ b/include/drm/bridge/dw_hdmi.h
|
||||
@@ -59,6 +59,7 @@ struct dw_hdmi_phy_ops {
|
||||
};
|
||||
|
||||
struct dw_hdmi_plat_data {
|
||||
+ struct regmap *regm;
|
||||
enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode);
|
||||
|
||||
--
|
||||
1.9.1
|
||||
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,115 @@
|
|||
From 8d012e114e251f5427cb46851ce47e43b745e6c3 Mon Sep 17 00:00:00 2001
|
||||
From: Nickey Yang <nickey.yang@rock-chips.com>
|
||||
Date: Mon, 20 Mar 2017 10:57:31 +0800
|
||||
Subject: [PATCH 41/93] drm/bridge: dw_hdmi: support i2c extended read mode
|
||||
|
||||
"I2C Master Interface Extended Read Mode" implements a segment
|
||||
pointer-based read operation using the Special Register configuration.
|
||||
|
||||
This patch fix https://patchwork.kernel.org/patch/7098101/ mentioned
|
||||
"The current implementation does not support "I2C Master Interface
|
||||
Extended Read Mode" to read data addressed by non-zero segment
|
||||
pointer, this means that if EDID has more than 1 extension blocks,
|
||||
EDID reading operation won't succeed"
|
||||
|
||||
With this patch, dw-hdmi can read EDID data with 1/2/4 blocks.
|
||||
|
||||
Signed-off-by: Nickey Yang <nickey.yang@rock-chips.com>
|
||||
Reviewed-by: Douglas Anderson <dianders@chromium.org>
|
||||
Acked-by: Vladimir Zapolskiy <vladimir_zapolskiy@mentor.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/1489978651-16647-1-git-send-email-nickey.yang@rock-chips.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 38 +++++++++++++++++++------------
|
||||
1 file changed, 24 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
index 026a0dc..0d112cf 100644
|
||||
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "dw-hdmi.h"
|
||||
#include "dw-hdmi-audio.h"
|
||||
|
||||
+#define DDC_SEGMENT_ADDR 0x30
|
||||
#define HDMI_EDID_LEN 512
|
||||
|
||||
#define RGB 0
|
||||
@@ -112,6 +113,7 @@ struct dw_hdmi_i2c {
|
||||
|
||||
u8 slave_reg;
|
||||
bool is_regaddr;
|
||||
+ bool is_segment;
|
||||
};
|
||||
|
||||
struct dw_hdmi_phy_data {
|
||||
@@ -247,8 +249,12 @@ static int dw_hdmi_i2c_read(struct dw_hdmi *hdmi,
|
||||
reinit_completion(&i2c->cmp);
|
||||
|
||||
hdmi_writeb(hdmi, i2c->slave_reg++, HDMI_I2CM_ADDRESS);
|
||||
- hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_READ,
|
||||
- HDMI_I2CM_OPERATION);
|
||||
+ if (i2c->is_segment)
|
||||
+ hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_READ_EXT,
|
||||
+ HDMI_I2CM_OPERATION);
|
||||
+ else
|
||||
+ hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_READ,
|
||||
+ HDMI_I2CM_OPERATION);
|
||||
|
||||
stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10);
|
||||
if (!stat)
|
||||
@@ -260,6 +266,7 @@ static int dw_hdmi_i2c_read(struct dw_hdmi *hdmi,
|
||||
|
||||
*buf++ = hdmi_readb(hdmi, HDMI_I2CM_DATAI);
|
||||
}
|
||||
+ i2c->is_segment = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -309,12 +316,6 @@ static int dw_hdmi_i2c_xfer(struct i2c_adapter *adap,
|
||||
dev_dbg(hdmi->dev, "xfer: num: %d, addr: %#x\n", num, addr);
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
- if (msgs[i].addr != addr) {
|
||||
- dev_warn(hdmi->dev,
|
||||
- "unsupported transfer, changed slave address\n");
|
||||
- return -EOPNOTSUPP;
|
||||
- }
|
||||
-
|
||||
if (msgs[i].len == 0) {
|
||||
dev_dbg(hdmi->dev,
|
||||
"unsupported transfer %d/%d, no data\n",
|
||||
@@ -334,15 +335,24 @@ static int dw_hdmi_i2c_xfer(struct i2c_adapter *adap,
|
||||
/* Set slave device register address on transfer */
|
||||
i2c->is_regaddr = false;
|
||||
|
||||
+ /* Set segment pointer for I2C extended read mode operation */
|
||||
+ i2c->is_segment = false;
|
||||
+
|
||||
for (i = 0; i < num; i++) {
|
||||
dev_dbg(hdmi->dev, "xfer: num: %d/%d, len: %d, flags: %#x\n",
|
||||
i + 1, num, msgs[i].len, msgs[i].flags);
|
||||
-
|
||||
- if (msgs[i].flags & I2C_M_RD)
|
||||
- ret = dw_hdmi_i2c_read(hdmi, msgs[i].buf, msgs[i].len);
|
||||
- else
|
||||
- ret = dw_hdmi_i2c_write(hdmi, msgs[i].buf, msgs[i].len);
|
||||
-
|
||||
+ if (msgs[i].addr == DDC_SEGMENT_ADDR && msgs[i].len == 1) {
|
||||
+ i2c->is_segment = true;
|
||||
+ hdmi_writeb(hdmi, DDC_SEGMENT_ADDR, HDMI_I2CM_SEGADDR);
|
||||
+ hdmi_writeb(hdmi, *msgs[i].buf, HDMI_I2CM_SEGPTR);
|
||||
+ } else {
|
||||
+ if (msgs[i].flags & I2C_M_RD)
|
||||
+ ret = dw_hdmi_i2c_read(hdmi, msgs[i].buf,
|
||||
+ msgs[i].len);
|
||||
+ else
|
||||
+ ret = dw_hdmi_i2c_write(hdmi, msgs[i].buf,
|
||||
+ msgs[i].len);
|
||||
+ }
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
From 7feb88b4b876148c48911d2c9733fcab0e877cd9 Mon Sep 17 00:00:00 2001
|
||||
From: Nickey Yang <nickey.yang@rock-chips.com>
|
||||
Date: Tue, 21 Mar 2017 15:36:17 +0800
|
||||
Subject: [PATCH 42/93] drm: bridge: dw-hdmi: add HDMI vendor specific
|
||||
infoframe config
|
||||
|
||||
Vendor specific infoframe is mandatory for 4K2K resolution.
|
||||
Without this, the HDMI protocol compliance fails.
|
||||
|
||||
Signed-off-by: Nickey Yang <nickey.yang@rock-chips.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/1490081777-2232-1-git-send-email-nickey.yang@rock-chips.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 53 +++++++++++++++++++++++++++++++
|
||||
drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 4 +++
|
||||
2 files changed, 57 insertions(+)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
index 0d112cf..af93f7a 100644
|
||||
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
@@ -1240,6 +1240,58 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
|
||||
hdmi_writeb(hdmi, (frame.right_bar >> 8) & 0xff, HDMI_FC_AVISRB1);
|
||||
}
|
||||
|
||||
+static void hdmi_config_vendor_specific_infoframe(struct dw_hdmi *hdmi,
|
||||
+ struct drm_display_mode *mode)
|
||||
+{
|
||||
+ struct hdmi_vendor_infoframe frame;
|
||||
+ u8 buffer[10];
|
||||
+ ssize_t err;
|
||||
+
|
||||
+ err = drm_hdmi_vendor_infoframe_from_display_mode(&frame, mode);
|
||||
+ if (err < 0)
|
||||
+ /*
|
||||
+ * Going into that statement does not means vendor infoframe
|
||||
+ * fails. It just informed us that vendor infoframe is not
|
||||
+ * needed for the selected mode. Only 4k or stereoscopic 3D
|
||||
+ * mode requires vendor infoframe. So just simply return.
|
||||
+ */
|
||||
+ return;
|
||||
+
|
||||
+ err = hdmi_vendor_infoframe_pack(&frame, buffer, sizeof(buffer));
|
||||
+ if (err < 0) {
|
||||
+ dev_err(hdmi->dev, "Failed to pack vendor infoframe: %zd\n",
|
||||
+ err);
|
||||
+ return;
|
||||
+ }
|
||||
+ hdmi_mask_writeb(hdmi, 0, HDMI_FC_DATAUTO0, HDMI_FC_DATAUTO0_VSD_OFFSET,
|
||||
+ HDMI_FC_DATAUTO0_VSD_MASK);
|
||||
+
|
||||
+ /* Set the length of HDMI vendor specific InfoFrame payload */
|
||||
+ hdmi_writeb(hdmi, buffer[2], HDMI_FC_VSDSIZE);
|
||||
+
|
||||
+ /* Set 24bit IEEE Registration Identifier */
|
||||
+ hdmi_writeb(hdmi, buffer[4], HDMI_FC_VSDIEEEID0);
|
||||
+ hdmi_writeb(hdmi, buffer[5], HDMI_FC_VSDIEEEID1);
|
||||
+ hdmi_writeb(hdmi, buffer[6], HDMI_FC_VSDIEEEID2);
|
||||
+
|
||||
+ /* Set HDMI_Video_Format and HDMI_VIC/3D_Structure */
|
||||
+ hdmi_writeb(hdmi, buffer[7], HDMI_FC_VSDPAYLOAD0);
|
||||
+ hdmi_writeb(hdmi, buffer[8], HDMI_FC_VSDPAYLOAD1);
|
||||
+
|
||||
+ if (frame.s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF)
|
||||
+ hdmi_writeb(hdmi, buffer[9], HDMI_FC_VSDPAYLOAD2);
|
||||
+
|
||||
+ /* Packet frame interpolation */
|
||||
+ hdmi_writeb(hdmi, 1, HDMI_FC_DATAUTO1);
|
||||
+
|
||||
+ /* Auto packets per frame and line spacing */
|
||||
+ hdmi_writeb(hdmi, 0x11, HDMI_FC_DATAUTO2);
|
||||
+
|
||||
+ /* Configures the Frame Composer On RDRB mode */
|
||||
+ hdmi_mask_writeb(hdmi, 1, HDMI_FC_DATAUTO0, HDMI_FC_DATAUTO0_VSD_OFFSET,
|
||||
+ HDMI_FC_DATAUTO0_VSD_MASK);
|
||||
+}
|
||||
+
|
||||
static void hdmi_av_composer(struct dw_hdmi *hdmi,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
@@ -1489,6 +1541,7 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
|
||||
|
||||
/* HDMI Initialization Step F - Configure AVI InfoFrame */
|
||||
hdmi_config_AVI(hdmi, mode);
|
||||
+ hdmi_config_vendor_specific_infoframe(hdmi, mode);
|
||||
} else {
|
||||
dev_dbg(hdmi->dev, "%s DVI mode\n", __func__);
|
||||
}
|
||||
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
|
||||
index 325b0b8..c59f87e 100644
|
||||
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
|
||||
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
|
||||
@@ -854,6 +854,10 @@ enum {
|
||||
HDMI_FC_DBGFORCE_FORCEAUDIO = 0x10,
|
||||
HDMI_FC_DBGFORCE_FORCEVIDEO = 0x1,
|
||||
|
||||
+/* FC_DATAUTO0 field values */
|
||||
+ HDMI_FC_DATAUTO0_VSD_MASK = 0x08,
|
||||
+ HDMI_FC_DATAUTO0_VSD_OFFSET = 3,
|
||||
+
|
||||
/* PHY_CONF0 field values */
|
||||
HDMI_PHY_CONF0_PDZ_MASK = 0x80,
|
||||
HDMI_PHY_CONF0_PDZ_OFFSET = 7,
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
From b880ce74954cefe49cfc101c684c4ce0b0063945 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Fri, 3 Mar 2017 14:14:56 +0200
|
||||
Subject: [PATCH 43/93] drm: bridge: dw-hdmi: Extract PHY interrupt setup to a
|
||||
function
|
||||
|
||||
In preparation for adding PHY operations to handle RX SENSE and HPD,
|
||||
group all the PHY interrupt setup code in a single location and extract
|
||||
it to a separate function.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
---
|
||||
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 50 ++++++++++++++-----------------
|
||||
1 file changed, 23 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
index af93f7a..f82750a 100644
|
||||
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
@@ -1559,7 +1559,7 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
|
||||
}
|
||||
|
||||
/* Wait until we are registered to enable interrupts */
|
||||
-static int dw_hdmi_fb_registered(struct dw_hdmi *hdmi)
|
||||
+static void dw_hdmi_fb_registered(struct dw_hdmi *hdmi)
|
||||
{
|
||||
hdmi_writeb(hdmi, HDMI_PHY_I2CM_INT_ADDR_DONE_POL,
|
||||
HDMI_PHY_I2CM_INT_ADDR);
|
||||
@@ -1567,15 +1567,6 @@ static int dw_hdmi_fb_registered(struct dw_hdmi *hdmi)
|
||||
hdmi_writeb(hdmi, HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL |
|
||||
HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL,
|
||||
HDMI_PHY_I2CM_CTLINT_ADDR);
|
||||
-
|
||||
- /* enable cable hot plug irq */
|
||||
- hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0);
|
||||
-
|
||||
- /* Clear Hotplug interrupts */
|
||||
- hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE,
|
||||
- HDMI_IH_PHY_STAT0);
|
||||
-
|
||||
- return 0;
|
||||
}
|
||||
|
||||
static void initialize_hdmi_ih_mutes(struct dw_hdmi *hdmi)
|
||||
@@ -1693,6 +1684,26 @@ static void dw_hdmi_update_phy_mask(struct dw_hdmi *hdmi)
|
||||
hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0);
|
||||
}
|
||||
|
||||
+static void dw_hdmi_phy_setup_hpd(struct dw_hdmi *hdmi)
|
||||
+{
|
||||
+ /*
|
||||
+ * Configure the PHY RX SENSE and HPD interrupts polarities and clear
|
||||
+ * any pending interrupt.
|
||||
+ */
|
||||
+ hdmi_writeb(hdmi, HDMI_PHY_HPD | HDMI_PHY_RX_SENSE, HDMI_PHY_POL0);
|
||||
+ hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE,
|
||||
+ HDMI_IH_PHY_STAT0);
|
||||
+
|
||||
+ /* Enable cable hot plug irq. */
|
||||
+ hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0);
|
||||
+
|
||||
+ /* Clear and unmute interrupts. */
|
||||
+ hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE,
|
||||
+ HDMI_IH_PHY_STAT0);
|
||||
+ hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE),
|
||||
+ HDMI_IH_MUTE_PHY_STAT0);
|
||||
+}
|
||||
+
|
||||
static enum drm_connector_status
|
||||
dw_hdmi_connector_detect(struct drm_connector *connector, bool force)
|
||||
{
|
||||
@@ -2204,29 +2215,14 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
|
||||
hdmi->ddc = NULL;
|
||||
}
|
||||
|
||||
- /*
|
||||
- * Configure registers related to HDMI interrupt
|
||||
- * generation before registering IRQ.
|
||||
- */
|
||||
- hdmi_writeb(hdmi, HDMI_PHY_HPD | HDMI_PHY_RX_SENSE, HDMI_PHY_POL0);
|
||||
-
|
||||
- /* Clear Hotplug interrupts */
|
||||
- hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE,
|
||||
- HDMI_IH_PHY_STAT0);
|
||||
-
|
||||
hdmi->bridge.driver_private = hdmi;
|
||||
hdmi->bridge.funcs = &dw_hdmi_bridge_funcs;
|
||||
#ifdef CONFIG_OF
|
||||
hdmi->bridge.of_node = pdev->dev.of_node;
|
||||
#endif
|
||||
|
||||
- ret = dw_hdmi_fb_registered(hdmi);
|
||||
- if (ret)
|
||||
- goto err_iahb;
|
||||
-
|
||||
- /* Unmute interrupts */
|
||||
- hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE),
|
||||
- HDMI_IH_MUTE_PHY_STAT0);
|
||||
+ dw_hdmi_fb_registered(hdmi);
|
||||
+ dw_hdmi_phy_setup_hpd(hdmi);
|
||||
|
||||
memset(&pdevinfo, 0, sizeof(pdevinfo));
|
||||
pdevinfo.parent = dev;
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,551 @@
|
|||
From 61801956e33a13e4682a8b52978d8f3c5d7f99e3 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Fri, 13 Jan 2017 16:07:42 +0100
|
||||
Subject: [PATCH 44/93] drm: bridge: dw-hdmi: Switch to V4L bus format and
|
||||
encodings
|
||||
|
||||
Some display pipelines can only provide non-RBG input pixels to the HDMI TX
|
||||
Controller, this patch takes the pixel format from the plat_data if provided.
|
||||
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 326 +++++++++++++++++++++---------
|
||||
include/drm/bridge/dw_hdmi.h | 63 ++++++
|
||||
2 files changed, 294 insertions(+), 95 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
index f82750a..fcb0a27 100644
|
||||
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
@@ -30,18 +30,15 @@
|
||||
#include <drm/drm_encoder_slave.h>
|
||||
#include <drm/bridge/dw_hdmi.h>
|
||||
|
||||
+#include <uapi/linux/media-bus-format.h>
|
||||
+#include <uapi/linux/videodev2.h>
|
||||
+
|
||||
#include "dw-hdmi.h"
|
||||
#include "dw-hdmi-audio.h"
|
||||
|
||||
#define DDC_SEGMENT_ADDR 0x30
|
||||
#define HDMI_EDID_LEN 512
|
||||
|
||||
-#define RGB 0
|
||||
-#define YCBCR444 1
|
||||
-#define YCBCR422_16BITS 2
|
||||
-#define YCBCR422_8BITS 3
|
||||
-#define XVYCC444 4
|
||||
-
|
||||
enum hdmi_datamap {
|
||||
RGB444_8B = 0x01,
|
||||
RGB444_10B = 0x03,
|
||||
@@ -95,10 +92,10 @@ struct hdmi_vmode {
|
||||
};
|
||||
|
||||
struct hdmi_data_info {
|
||||
- unsigned int enc_in_format;
|
||||
- unsigned int enc_out_format;
|
||||
- unsigned int enc_color_depth;
|
||||
- unsigned int colorimetry;
|
||||
+ unsigned int enc_in_bus_format;
|
||||
+ unsigned int enc_out_bus_format;
|
||||
+ unsigned int enc_in_encoding;
|
||||
+ unsigned int enc_out_encoding;
|
||||
unsigned int pix_repet_factor;
|
||||
unsigned int hdcp_enable;
|
||||
struct hdmi_vmode video_mode;
|
||||
@@ -567,6 +564,92 @@ void dw_hdmi_audio_disable(struct dw_hdmi *hdmi)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dw_hdmi_audio_disable);
|
||||
|
||||
+static bool hdmi_bus_fmt_is_rgb(unsigned int bus_format)
|
||||
+{
|
||||
+ switch (bus_format) {
|
||||
+ case MEDIA_BUS_FMT_RGB888_1X24:
|
||||
+ case MEDIA_BUS_FMT_RGB101010_1X30:
|
||||
+ case MEDIA_BUS_FMT_RGB121212_1X36:
|
||||
+ case MEDIA_BUS_FMT_RGB161616_1X48:
|
||||
+ return true;
|
||||
+
|
||||
+ default:
|
||||
+ return false;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static bool hdmi_bus_fmt_is_yuv444(unsigned int bus_format)
|
||||
+{
|
||||
+ switch (bus_format) {
|
||||
+ case MEDIA_BUS_FMT_YUV8_1X24:
|
||||
+ case MEDIA_BUS_FMT_YUV10_1X30:
|
||||
+ case MEDIA_BUS_FMT_YUV12_1X36:
|
||||
+ case MEDIA_BUS_FMT_YUV16_1X48:
|
||||
+ return true;
|
||||
+
|
||||
+ default:
|
||||
+ return false;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static bool hdmi_bus_fmt_is_yuv422(unsigned int bus_format)
|
||||
+{
|
||||
+ switch (bus_format) {
|
||||
+ case MEDIA_BUS_FMT_UYVY8_1X16:
|
||||
+ case MEDIA_BUS_FMT_UYVY10_1X20:
|
||||
+ case MEDIA_BUS_FMT_UYVY12_1X24:
|
||||
+ return true;
|
||||
+
|
||||
+ default:
|
||||
+ return false;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static bool hdmi_bus_fmt_is_yuv420(unsigned int bus_format)
|
||||
+{
|
||||
+ switch (bus_format) {
|
||||
+ case MEDIA_BUS_FMT_UYYVYY8_1X24:
|
||||
+ case MEDIA_BUS_FMT_UYYVYY10_1X30:
|
||||
+ case MEDIA_BUS_FMT_UYYVYY12_1X36:
|
||||
+ case MEDIA_BUS_FMT_UYYVYY16_1X48:
|
||||
+ return true;
|
||||
+
|
||||
+ default:
|
||||
+ return false;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int hdmi_bus_fmt_color_depth(unsigned int bus_format)
|
||||
+{
|
||||
+ switch (bus_format) {
|
||||
+ case MEDIA_BUS_FMT_RGB888_1X24:
|
||||
+ case MEDIA_BUS_FMT_YUV8_1X24:
|
||||
+ case MEDIA_BUS_FMT_UYVY8_1X16:
|
||||
+ case MEDIA_BUS_FMT_UYYVYY8_1X24:
|
||||
+ return 8;
|
||||
+
|
||||
+ case MEDIA_BUS_FMT_RGB101010_1X30:
|
||||
+ case MEDIA_BUS_FMT_YUV10_1X30:
|
||||
+ case MEDIA_BUS_FMT_UYVY10_1X20:
|
||||
+ case MEDIA_BUS_FMT_UYYVYY10_1X30:
|
||||
+ return 10;
|
||||
+
|
||||
+ case MEDIA_BUS_FMT_RGB121212_1X36:
|
||||
+ case MEDIA_BUS_FMT_YUV12_1X36:
|
||||
+ case MEDIA_BUS_FMT_UYVY12_1X24:
|
||||
+ case MEDIA_BUS_FMT_UYYVYY12_1X36:
|
||||
+ return 12;
|
||||
+
|
||||
+ case MEDIA_BUS_FMT_RGB161616_1X48:
|
||||
+ case MEDIA_BUS_FMT_YUV16_1X48:
|
||||
+ case MEDIA_BUS_FMT_UYYVYY16_1X48:
|
||||
+ return 16;
|
||||
+
|
||||
+ default:
|
||||
+ return 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* this submodule is responsible for the video data synchronization.
|
||||
* for example, for RGB 4:4:4 input, the data map is defined as
|
||||
@@ -579,37 +662,49 @@ static void hdmi_video_sample(struct dw_hdmi *hdmi)
|
||||
int color_format = 0;
|
||||
u8 val;
|
||||
|
||||
- if (hdmi->hdmi_data.enc_in_format == RGB) {
|
||||
- if (hdmi->hdmi_data.enc_color_depth == 8)
|
||||
- color_format = 0x01;
|
||||
- else if (hdmi->hdmi_data.enc_color_depth == 10)
|
||||
- color_format = 0x03;
|
||||
- else if (hdmi->hdmi_data.enc_color_depth == 12)
|
||||
- color_format = 0x05;
|
||||
- else if (hdmi->hdmi_data.enc_color_depth == 16)
|
||||
- color_format = 0x07;
|
||||
- else
|
||||
- return;
|
||||
- } else if (hdmi->hdmi_data.enc_in_format == YCBCR444) {
|
||||
- if (hdmi->hdmi_data.enc_color_depth == 8)
|
||||
- color_format = 0x09;
|
||||
- else if (hdmi->hdmi_data.enc_color_depth == 10)
|
||||
- color_format = 0x0B;
|
||||
- else if (hdmi->hdmi_data.enc_color_depth == 12)
|
||||
- color_format = 0x0D;
|
||||
- else if (hdmi->hdmi_data.enc_color_depth == 16)
|
||||
- color_format = 0x0F;
|
||||
- else
|
||||
- return;
|
||||
- } else if (hdmi->hdmi_data.enc_in_format == YCBCR422_8BITS) {
|
||||
- if (hdmi->hdmi_data.enc_color_depth == 8)
|
||||
- color_format = 0x16;
|
||||
- else if (hdmi->hdmi_data.enc_color_depth == 10)
|
||||
- color_format = 0x14;
|
||||
- else if (hdmi->hdmi_data.enc_color_depth == 12)
|
||||
- color_format = 0x12;
|
||||
- else
|
||||
- return;
|
||||
+ switch (hdmi->hdmi_data.enc_in_bus_format) {
|
||||
+ case MEDIA_BUS_FMT_RGB888_1X24:
|
||||
+ color_format = 0x01;
|
||||
+ break;
|
||||
+ case MEDIA_BUS_FMT_RGB101010_1X30:
|
||||
+ color_format = 0x03;
|
||||
+ break;
|
||||
+ case MEDIA_BUS_FMT_RGB121212_1X36:
|
||||
+ color_format = 0x05;
|
||||
+ break;
|
||||
+ case MEDIA_BUS_FMT_RGB161616_1X48:
|
||||
+ color_format = 0x07;
|
||||
+ break;
|
||||
+
|
||||
+ case MEDIA_BUS_FMT_YUV8_1X24:
|
||||
+ case MEDIA_BUS_FMT_UYYVYY8_1X24:
|
||||
+ color_format = 0x09;
|
||||
+ break;
|
||||
+ case MEDIA_BUS_FMT_YUV10_1X30:
|
||||
+ case MEDIA_BUS_FMT_UYYVYY10_1X30:
|
||||
+ color_format = 0x0B;
|
||||
+ break;
|
||||
+ case MEDIA_BUS_FMT_YUV12_1X36:
|
||||
+ case MEDIA_BUS_FMT_UYYVYY12_1X36:
|
||||
+ color_format = 0x0D;
|
||||
+ break;
|
||||
+ case MEDIA_BUS_FMT_YUV16_1X48:
|
||||
+ case MEDIA_BUS_FMT_UYYVYY16_1X48:
|
||||
+ color_format = 0x0F;
|
||||
+ break;
|
||||
+
|
||||
+ case MEDIA_BUS_FMT_UYVY8_1X16:
|
||||
+ color_format = 0x16;
|
||||
+ break;
|
||||
+ case MEDIA_BUS_FMT_UYVY10_1X20:
|
||||
+ color_format = 0x14;
|
||||
+ break;
|
||||
+ case MEDIA_BUS_FMT_UYVY12_1X24:
|
||||
+ color_format = 0x12;
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ return;
|
||||
}
|
||||
|
||||
val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE |
|
||||
@@ -632,26 +727,30 @@ static void hdmi_video_sample(struct dw_hdmi *hdmi)
|
||||
|
||||
static int is_color_space_conversion(struct dw_hdmi *hdmi)
|
||||
{
|
||||
- return hdmi->hdmi_data.enc_in_format != hdmi->hdmi_data.enc_out_format;
|
||||
+ return hdmi->hdmi_data.enc_in_bus_format != hdmi->hdmi_data.enc_out_bus_format;
|
||||
}
|
||||
|
||||
static int is_color_space_decimation(struct dw_hdmi *hdmi)
|
||||
{
|
||||
- if (hdmi->hdmi_data.enc_out_format != YCBCR422_8BITS)
|
||||
+ if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format))
|
||||
return 0;
|
||||
- if (hdmi->hdmi_data.enc_in_format == RGB ||
|
||||
- hdmi->hdmi_data.enc_in_format == YCBCR444)
|
||||
+
|
||||
+ if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_in_bus_format) ||
|
||||
+ hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_in_bus_format))
|
||||
return 1;
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int is_color_space_interpolation(struct dw_hdmi *hdmi)
|
||||
{
|
||||
- if (hdmi->hdmi_data.enc_in_format != YCBCR422_8BITS)
|
||||
+ if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_in_bus_format))
|
||||
return 0;
|
||||
- if (hdmi->hdmi_data.enc_out_format == RGB ||
|
||||
- hdmi->hdmi_data.enc_out_format == YCBCR444)
|
||||
+
|
||||
+ if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format) ||
|
||||
+ hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format))
|
||||
return 1;
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -662,15 +761,16 @@ static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi)
|
||||
u32 csc_scale = 1;
|
||||
|
||||
if (is_color_space_conversion(hdmi)) {
|
||||
- if (hdmi->hdmi_data.enc_out_format == RGB) {
|
||||
- if (hdmi->hdmi_data.colorimetry ==
|
||||
- HDMI_COLORIMETRY_ITU_601)
|
||||
+ if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) {
|
||||
+ if (hdmi->hdmi_data.enc_out_encoding ==
|
||||
+ V4L2_YCBCR_ENC_601)
|
||||
csc_coeff = &csc_coeff_rgb_out_eitu601;
|
||||
else
|
||||
csc_coeff = &csc_coeff_rgb_out_eitu709;
|
||||
- } else if (hdmi->hdmi_data.enc_in_format == RGB) {
|
||||
- if (hdmi->hdmi_data.colorimetry ==
|
||||
- HDMI_COLORIMETRY_ITU_601)
|
||||
+ } else if (hdmi_bus_fmt_is_rgb(
|
||||
+ hdmi->hdmi_data.enc_in_bus_format)) {
|
||||
+ if (hdmi->hdmi_data.enc_out_encoding ==
|
||||
+ V4L2_YCBCR_ENC_601)
|
||||
csc_coeff = &csc_coeff_rgb_in_eitu601;
|
||||
else
|
||||
csc_coeff = &csc_coeff_rgb_in_eitu709;
|
||||
@@ -708,16 +808,23 @@ static void hdmi_video_csc(struct dw_hdmi *hdmi)
|
||||
else if (is_color_space_decimation(hdmi))
|
||||
decimation = HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3;
|
||||
|
||||
- if (hdmi->hdmi_data.enc_color_depth == 8)
|
||||
+ switch (hdmi_bus_fmt_color_depth(hdmi->hdmi_data.enc_out_bus_format)) {
|
||||
+ case 8:
|
||||
color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP;
|
||||
- else if (hdmi->hdmi_data.enc_color_depth == 10)
|
||||
+ break;
|
||||
+ case 10:
|
||||
color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP;
|
||||
- else if (hdmi->hdmi_data.enc_color_depth == 12)
|
||||
+ break;
|
||||
+ case 12:
|
||||
color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP;
|
||||
- else if (hdmi->hdmi_data.enc_color_depth == 16)
|
||||
+ break;
|
||||
+ case 16:
|
||||
color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP;
|
||||
- else
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
return;
|
||||
+ }
|
||||
|
||||
/* Configure the CSC registers */
|
||||
hdmi_writeb(hdmi, interpolation | decimation, HDMI_CSC_CFG);
|
||||
@@ -740,32 +847,43 @@ static void hdmi_video_packetize(struct dw_hdmi *hdmi)
|
||||
struct hdmi_data_info *hdmi_data = &hdmi->hdmi_data;
|
||||
u8 val, vp_conf;
|
||||
|
||||
- if (hdmi_data->enc_out_format == RGB ||
|
||||
- hdmi_data->enc_out_format == YCBCR444) {
|
||||
- if (!hdmi_data->enc_color_depth) {
|
||||
- output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
|
||||
- } else if (hdmi_data->enc_color_depth == 8) {
|
||||
+ if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format) ||
|
||||
+ hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format)) {
|
||||
+ switch (hdmi_bus_fmt_color_depth(
|
||||
+ hdmi->hdmi_data.enc_out_bus_format)) {
|
||||
+ case 8:
|
||||
color_depth = 4;
|
||||
output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
|
||||
- } else if (hdmi_data->enc_color_depth == 10) {
|
||||
+ break;
|
||||
+ case 10:
|
||||
color_depth = 5;
|
||||
- } else if (hdmi_data->enc_color_depth == 12) {
|
||||
+ break;
|
||||
+ case 12:
|
||||
color_depth = 6;
|
||||
- } else if (hdmi_data->enc_color_depth == 16) {
|
||||
+ break;
|
||||
+ case 16:
|
||||
color_depth = 7;
|
||||
- } else {
|
||||
- return;
|
||||
+ break;
|
||||
+ default:
|
||||
+ output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
|
||||
}
|
||||
- } else if (hdmi_data->enc_out_format == YCBCR422_8BITS) {
|
||||
- if (!hdmi_data->enc_color_depth ||
|
||||
- hdmi_data->enc_color_depth == 8)
|
||||
+ } else if (hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format)) {
|
||||
+ switch (hdmi_bus_fmt_color_depth(
|
||||
+ hdmi->hdmi_data.enc_out_bus_format)) {
|
||||
+ case 0:
|
||||
+ case 8:
|
||||
remap_size = HDMI_VP_REMAP_YCC422_16bit;
|
||||
- else if (hdmi_data->enc_color_depth == 10)
|
||||
+ break;
|
||||
+ case 10:
|
||||
remap_size = HDMI_VP_REMAP_YCC422_20bit;
|
||||
- else if (hdmi_data->enc_color_depth == 12)
|
||||
+ break;
|
||||
+ case 12:
|
||||
remap_size = HDMI_VP_REMAP_YCC422_24bit;
|
||||
- else
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
return;
|
||||
+ }
|
||||
output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422;
|
||||
} else {
|
||||
return;
|
||||
@@ -1148,28 +1266,35 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
|
||||
/* Initialise info frame from DRM mode */
|
||||
drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
|
||||
|
||||
- if (hdmi->hdmi_data.enc_out_format == YCBCR444)
|
||||
+ if (hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format))
|
||||
frame.colorspace = HDMI_COLORSPACE_YUV444;
|
||||
- else if (hdmi->hdmi_data.enc_out_format == YCBCR422_8BITS)
|
||||
+ else if (hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format))
|
||||
frame.colorspace = HDMI_COLORSPACE_YUV422;
|
||||
else
|
||||
frame.colorspace = HDMI_COLORSPACE_RGB;
|
||||
|
||||
/* Set up colorimetry */
|
||||
- if (hdmi->hdmi_data.enc_out_format == XVYCC444) {
|
||||
- frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
|
||||
- if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601)
|
||||
- frame.extended_colorimetry =
|
||||
+ switch (hdmi->hdmi_data.enc_out_encoding) {
|
||||
+ case V4L2_YCBCR_ENC_601:
|
||||
+ if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV601)
|
||||
+ frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
|
||||
+ else
|
||||
+ frame.colorimetry = HDMI_COLORIMETRY_ITU_601;
|
||||
+ frame.extended_colorimetry =
|
||||
HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
|
||||
- else /*hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_709*/
|
||||
- frame.extended_colorimetry =
|
||||
+ case V4L2_YCBCR_ENC_709:
|
||||
+ if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV709)
|
||||
+ frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
|
||||
+ else
|
||||
+ frame.colorimetry = HDMI_COLORIMETRY_ITU_709;
|
||||
+ frame.extended_colorimetry =
|
||||
HDMI_EXTENDED_COLORIMETRY_XV_YCC_709;
|
||||
- } else if (hdmi->hdmi_data.enc_out_format != RGB) {
|
||||
- frame.colorimetry = hdmi->hdmi_data.colorimetry;
|
||||
- frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
|
||||
- } else { /* Carries no data */
|
||||
- frame.colorimetry = HDMI_COLORIMETRY_NONE;
|
||||
- frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
|
||||
+ break;
|
||||
+ default: /* Carries no data */
|
||||
+ frame.colorimetry = HDMI_COLORIMETRY_ITU_601;
|
||||
+ frame.extended_colorimetry =
|
||||
+ HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
|
||||
+ break;
|
||||
}
|
||||
|
||||
frame.scan_mode = HDMI_SCAN_MODE_NONE;
|
||||
@@ -1498,19 +1623,30 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
|
||||
(hdmi->vic == 21) || (hdmi->vic == 22) ||
|
||||
(hdmi->vic == 2) || (hdmi->vic == 3) ||
|
||||
(hdmi->vic == 17) || (hdmi->vic == 18))
|
||||
- hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_601;
|
||||
+ hdmi->hdmi_data.enc_out_encoding = V4L2_YCBCR_ENC_601;
|
||||
else
|
||||
- hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709;
|
||||
+ hdmi->hdmi_data.enc_out_encoding = V4L2_YCBCR_ENC_709;
|
||||
|
||||
hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0;
|
||||
hdmi->hdmi_data.video_mode.mpixelrepetitioninput = 0;
|
||||
|
||||
- /* TODO: Get input format from IPU (via FB driver interface) */
|
||||
- hdmi->hdmi_data.enc_in_format = RGB;
|
||||
+ /* TOFIX: Get input format from plat data or fallback to RGB888 */
|
||||
+ if (hdmi->plat_data->input_bus_format >= 0)
|
||||
+ hdmi->hdmi_data.enc_in_bus_format =
|
||||
+ hdmi->plat_data->input_bus_format;
|
||||
+ else
|
||||
+ hdmi->hdmi_data.enc_in_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
|
||||
+
|
||||
+ /* TOFIX: Get input encoding from plat data or fallback to none */
|
||||
+ if (hdmi->plat_data->input_bus_encoding >= 0)
|
||||
+ hdmi->hdmi_data.enc_in_encoding =
|
||||
+ hdmi->plat_data->input_bus_encoding;
|
||||
+ else
|
||||
+ hdmi->hdmi_data.enc_in_encoding = V4L2_YCBCR_ENC_DEFAULT;
|
||||
|
||||
- hdmi->hdmi_data.enc_out_format = RGB;
|
||||
+ /* TOFIX: Default to RGB888 output format */
|
||||
+ hdmi->hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
|
||||
|
||||
- hdmi->hdmi_data.enc_color_depth = 8;
|
||||
hdmi->hdmi_data.pix_repet_factor = 0;
|
||||
hdmi->hdmi_data.hdcp_enable = 0;
|
||||
hdmi->hdmi_data.video_mode.mdataenablepolarity = true;
|
||||
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
|
||||
index bcceee8..0da74fb 100644
|
||||
--- a/include/drm/bridge/dw_hdmi.h
|
||||
+++ b/include/drm/bridge/dw_hdmi.h
|
||||
@@ -14,6 +14,67 @@
|
||||
|
||||
struct dw_hdmi;
|
||||
|
||||
+/**
|
||||
+ * DOC: Supported input formats and encodings
|
||||
+ *
|
||||
+ * Depending on the Hardware configuration of the Controller IP, it supports
|
||||
+ * a subset of the following input formats and encodings on it's internal
|
||||
+ * 48bit bus.
|
||||
+ *
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + Format Name + Format Code + Encodings +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + RGB 4:4:4 8bit + ``MEDIA_BUS_FMT_RGB888_1X24`` + ``V4L2_YCBCR_ENC_DEFAULT`` +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + RGB 4:4:4 10bits + ``MEDIA_BUS_FMT_RGB101010_1X30``+ ``V4L2_YCBCR_ENC_DEFAULT`` +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + RGB 4:4:4 12bits + ``MEDIA_BUS_FMT_RGB121212_1X36``+ ``V4L2_YCBCR_ENC_DEFAULT`` +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + RGB 4:4:4 16bits + ``MEDIA_BUS_FMT_RGB161616_1X48``+ ``V4L2_YCBCR_ENC_DEFAULT`` +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + YCbCr 4:4:4 8bit + ``MEDIA_BUS_FMT_YUV8_1X24`` + ``V4L2_YCBCR_ENC_601`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_709`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_XV601`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_XV709`` +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + YCbCr 4:4:4 10bits + ``MEDIA_BUS_FMT_YUV10_1X30`` + ``V4L2_YCBCR_ENC_601`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_709`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_XV601`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_XV709`` +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + YCbCr 4:4:4 12bits + ``MEDIA_BUS_FMT_YUV12_1X36`` + ``V4L2_YCBCR_ENC_601`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_709`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_XV601`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_XV709`` +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + YCbCr 4:4:4 16bits + ``MEDIA_BUS_FMT_YUV16_1X48`` + ``V4L2_YCBCR_ENC_601`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_709`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_XV601`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_XV709`` +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + YCbCr 4:2:2 8bit + ``MEDIA_BUS_FMT_UYVY8_1X16`` + ``V4L2_YCBCR_ENC_601`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_709`` +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + YCbCr 4:2:2 10bits + ``MEDIA_BUS_FMT_UYVY10_1X20`` + ``V4L2_YCBCR_ENC_601`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_709`` +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + YCbCr 4:2:2 12bits + ``MEDIA_BUS_FMT_UYVY12_1X24`` + ``V4L2_YCBCR_ENC_601`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_709`` +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + YCbCr 4:2:0 8bit + ``MEDIA_BUS_FMT_UYYVYY8_1X24`` + ``V4L2_YCBCR_ENC_601`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_709`` +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + YCbCr 4:2:0 10bits + ``MEDIA_BUS_FMT_UYYVYY10_1X30`` + ``V4L2_YCBCR_ENC_601`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_709`` +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + YCbCr 4:2:0 12bits + ``MEDIA_BUS_FMT_UYYVYY12_1X36`` + ``V4L2_YCBCR_ENC_601`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_709`` +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + YCbCr 4:2:0 16bits + ``MEDIA_BUS_FMT_UYYVYY16_1X48`` + ``V4L2_YCBCR_ENC_601`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_709`` +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ */
|
||||
+
|
||||
enum {
|
||||
DW_HDMI_RES_8,
|
||||
DW_HDMI_RES_10,
|
||||
@@ -62,6 +123,8 @@ struct dw_hdmi_plat_data {
|
||||
struct regmap *regm;
|
||||
enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode);
|
||||
+ unsigned long input_bus_format;
|
||||
+ unsigned long input_bus_encoding;
|
||||
|
||||
/* Vendor PHY support */
|
||||
const struct dw_hdmi_phy_ops *phy_ops;
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,225 @@
|
|||
From 5c5f665a2f6a9a8248bf38356f0958772d6d4ef6 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Wed, 8 Feb 2017 12:29:19 +0100
|
||||
Subject: [PATCH 45/93] drm: bridge: dw-hdmi: Move HPD handling to PHY
|
||||
operations
|
||||
|
||||
The HDMI TX controller support HPD and RXSENSE signaling from the PHY
|
||||
via it's STAT0 PHY interface, but some vendor PHYs can manage these
|
||||
signals independently from the controller, thus these STAT0 handling
|
||||
should be moved to PHY specific operations and become optional.
|
||||
|
||||
The existing STAT0 HPD and RXSENSE handling code is refactored into
|
||||
a supplementaty set of default PHY operations that are used automatically
|
||||
when the platform glue doesn't provide its own operations.
|
||||
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
---
|
||||
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 135 ++++++++++++++++++------------
|
||||
include/drm/bridge/dw_hdmi.h | 5 ++
|
||||
2 files changed, 86 insertions(+), 54 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
index fcb0a27..910d579 100644
|
||||
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
@@ -1229,10 +1229,46 @@ static enum drm_connector_status dw_hdmi_phy_read_hpd(struct dw_hdmi *hdmi,
|
||||
connector_status_connected : connector_status_disconnected;
|
||||
}
|
||||
|
||||
+static void dw_hdmi_phy_update_hpd(struct dw_hdmi *hdmi, void *data,
|
||||
+ bool force, bool disabled, bool rxsense)
|
||||
+{
|
||||
+ u8 old_mask = hdmi->phy_mask;
|
||||
+
|
||||
+ if (force || disabled || !rxsense)
|
||||
+ hdmi->phy_mask |= HDMI_PHY_RX_SENSE;
|
||||
+ else
|
||||
+ hdmi->phy_mask &= ~HDMI_PHY_RX_SENSE;
|
||||
+
|
||||
+ if (old_mask != hdmi->phy_mask)
|
||||
+ hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0);
|
||||
+}
|
||||
+
|
||||
+static void dw_hdmi_phy_setup_hpd(struct dw_hdmi *hdmi, void *data)
|
||||
+{
|
||||
+ /*
|
||||
+ * Configure the PHY RX SENSE and HPD interrupts polarities and clear
|
||||
+ * any pending interrupt.
|
||||
+ */
|
||||
+ hdmi_writeb(hdmi, HDMI_PHY_HPD | HDMI_PHY_RX_SENSE, HDMI_PHY_POL0);
|
||||
+ hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE,
|
||||
+ HDMI_IH_PHY_STAT0);
|
||||
+
|
||||
+ /* Enable cable hot plug irq. */
|
||||
+ hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0);
|
||||
+
|
||||
+ /* Clear and unmute interrupts. */
|
||||
+ hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE,
|
||||
+ HDMI_IH_PHY_STAT0);
|
||||
+ hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE),
|
||||
+ HDMI_IH_MUTE_PHY_STAT0);
|
||||
+}
|
||||
+
|
||||
static const struct dw_hdmi_phy_ops dw_hdmi_synopsys_phy_ops = {
|
||||
.init = dw_hdmi_phy_init,
|
||||
.disable = dw_hdmi_phy_disable,
|
||||
.read_hpd = dw_hdmi_phy_read_hpd,
|
||||
+ .update_hpd = dw_hdmi_phy_update_hpd,
|
||||
+ .setup_hpd = dw_hdmi_phy_setup_hpd,
|
||||
};
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
@@ -1809,35 +1845,10 @@ static void dw_hdmi_update_power(struct dw_hdmi *hdmi)
|
||||
*/
|
||||
static void dw_hdmi_update_phy_mask(struct dw_hdmi *hdmi)
|
||||
{
|
||||
- u8 old_mask = hdmi->phy_mask;
|
||||
-
|
||||
- if (hdmi->force || hdmi->disabled || !hdmi->rxsense)
|
||||
- hdmi->phy_mask |= HDMI_PHY_RX_SENSE;
|
||||
- else
|
||||
- hdmi->phy_mask &= ~HDMI_PHY_RX_SENSE;
|
||||
-
|
||||
- if (old_mask != hdmi->phy_mask)
|
||||
- hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0);
|
||||
-}
|
||||
-
|
||||
-static void dw_hdmi_phy_setup_hpd(struct dw_hdmi *hdmi)
|
||||
-{
|
||||
- /*
|
||||
- * Configure the PHY RX SENSE and HPD interrupts polarities and clear
|
||||
- * any pending interrupt.
|
||||
- */
|
||||
- hdmi_writeb(hdmi, HDMI_PHY_HPD | HDMI_PHY_RX_SENSE, HDMI_PHY_POL0);
|
||||
- hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE,
|
||||
- HDMI_IH_PHY_STAT0);
|
||||
-
|
||||
- /* Enable cable hot plug irq. */
|
||||
- hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0);
|
||||
-
|
||||
- /* Clear and unmute interrupts. */
|
||||
- hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE,
|
||||
- HDMI_IH_PHY_STAT0);
|
||||
- hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE),
|
||||
- HDMI_IH_MUTE_PHY_STAT0);
|
||||
+ if (hdmi->phy.ops->update_hpd)
|
||||
+ hdmi->phy.ops->update_hpd(hdmi, hdmi->phy.data,
|
||||
+ hdmi->force, hdmi->disabled,
|
||||
+ hdmi->rxsense);
|
||||
}
|
||||
|
||||
static enum drm_connector_status
|
||||
@@ -2029,6 +2040,41 @@ static irqreturn_t dw_hdmi_hardirq(int irq, void *dev_id)
|
||||
return ret;
|
||||
}
|
||||
|
||||
+void __dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense)
|
||||
+{
|
||||
+ mutex_lock(&hdmi->mutex);
|
||||
+
|
||||
+ if (!hdmi->disabled && !hdmi->force) {
|
||||
+ /*
|
||||
+ * If the RX sense status indicates we're disconnected,
|
||||
+ * clear the software rxsense status.
|
||||
+ */
|
||||
+ if (!rx_sense)
|
||||
+ hdmi->rxsense = false;
|
||||
+
|
||||
+ /*
|
||||
+ * Only set the software rxsense status when both
|
||||
+ * rxsense and hpd indicates we're connected.
|
||||
+ * This avoids what seems to be bad behaviour in
|
||||
+ * at least iMX6S versions of the phy.
|
||||
+ */
|
||||
+ if (hpd)
|
||||
+ hdmi->rxsense = true;
|
||||
+
|
||||
+ dw_hdmi_update_power(hdmi);
|
||||
+ dw_hdmi_update_phy_mask(hdmi);
|
||||
+ }
|
||||
+ mutex_unlock(&hdmi->mutex);
|
||||
+}
|
||||
+
|
||||
+void dw_hdmi_setup_rx_sense(struct device *dev, bool hpd, bool rx_sense)
|
||||
+{
|
||||
+ struct dw_hdmi *hdmi = dev_get_drvdata(dev);
|
||||
+
|
||||
+ __dw_hdmi_setup_rx_sense(hdmi, hpd, rx_sense);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(dw_hdmi_setup_rx_sense);
|
||||
+
|
||||
static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct dw_hdmi *hdmi = dev_id;
|
||||
@@ -2061,30 +2107,10 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
* ask the source to re-read the EDID.
|
||||
*/
|
||||
if (intr_stat &
|
||||
- (HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD)) {
|
||||
- mutex_lock(&hdmi->mutex);
|
||||
- if (!hdmi->disabled && !hdmi->force) {
|
||||
- /*
|
||||
- * If the RX sense status indicates we're disconnected,
|
||||
- * clear the software rxsense status.
|
||||
- */
|
||||
- if (!(phy_stat & HDMI_PHY_RX_SENSE))
|
||||
- hdmi->rxsense = false;
|
||||
-
|
||||
- /*
|
||||
- * Only set the software rxsense status when both
|
||||
- * rxsense and hpd indicates we're connected.
|
||||
- * This avoids what seems to be bad behaviour in
|
||||
- * at least iMX6S versions of the phy.
|
||||
- */
|
||||
- if (phy_stat & HDMI_PHY_HPD)
|
||||
- hdmi->rxsense = true;
|
||||
-
|
||||
- dw_hdmi_update_power(hdmi);
|
||||
- dw_hdmi_update_phy_mask(hdmi);
|
||||
- }
|
||||
- mutex_unlock(&hdmi->mutex);
|
||||
- }
|
||||
+ (HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD))
|
||||
+ __dw_hdmi_setup_rx_sense(hdmi,
|
||||
+ phy_stat & HDMI_PHY_HPD,
|
||||
+ phy_stat & HDMI_PHY_RX_SENSE);
|
||||
|
||||
if (intr_stat & HDMI_IH_PHY_STAT0_HPD) {
|
||||
dev_dbg(hdmi->dev, "EVENT=%s\n",
|
||||
@@ -2358,7 +2384,8 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
|
||||
#endif
|
||||
|
||||
dw_hdmi_fb_registered(hdmi);
|
||||
- dw_hdmi_phy_setup_hpd(hdmi);
|
||||
+ if (hdmi->phy.ops->setup_hpd)
|
||||
+ hdmi->phy.ops->setup_hpd(hdmi, hdmi->phy.data);
|
||||
|
||||
memset(&pdevinfo, 0, sizeof(pdevinfo));
|
||||
pdevinfo.parent = dev;
|
||||
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
|
||||
index 0da74fb..0668ae1 100644
|
||||
--- a/include/drm/bridge/dw_hdmi.h
|
||||
+++ b/include/drm/bridge/dw_hdmi.h
|
||||
@@ -117,6 +117,9 @@ struct dw_hdmi_phy_ops {
|
||||
struct drm_display_mode *mode);
|
||||
void (*disable)(struct dw_hdmi *hdmi, void *data);
|
||||
enum drm_connector_status (*read_hpd)(struct dw_hdmi *hdmi, void *data);
|
||||
+ void (*update_hpd)(struct dw_hdmi *hdmi, void *data,
|
||||
+ bool force, bool disabled, bool rxsense);
|
||||
+ void (*setup_hpd)(struct dw_hdmi *hdmi, void *data);
|
||||
};
|
||||
|
||||
struct dw_hdmi_plat_data {
|
||||
@@ -147,6 +150,8 @@ int dw_hdmi_probe(struct platform_device *pdev,
|
||||
int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
|
||||
const struct dw_hdmi_plat_data *plat_data);
|
||||
|
||||
+void dw_hdmi_setup_rx_sense(struct device *dev, bool hpd, bool rx_sense);
|
||||
+
|
||||
void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate);
|
||||
void dw_hdmi_audio_enable(struct dw_hdmi *hdmi);
|
||||
void dw_hdmi_audio_disable(struct dw_hdmi *hdmi);
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
From 050ccc8152e10f6d8ae44cf6772a78331d8df19e Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Thu, 2 Feb 2017 10:47:43 +0100
|
||||
Subject: [PATCH 46/93] drm: meson: rename module name to meson-drm
|
||||
|
||||
The module is currently named "meson.ko" which can lead to some
|
||||
confusion, this patches renames it "meson-drm.ko"
|
||||
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/1486028864-19622-2-git-send-email-narmstrong@baylibre.com
|
||||
---
|
||||
drivers/gpu/drm/meson/Makefile | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/meson/Makefile b/drivers/gpu/drm/meson/Makefile
|
||||
index 2591978..92cf845 100644
|
||||
--- a/drivers/gpu/drm/meson/Makefile
|
||||
+++ b/drivers/gpu/drm/meson/Makefile
|
||||
@@ -1,4 +1,4 @@
|
||||
-meson-y := meson_drv.o meson_plane.o meson_crtc.o meson_venc_cvbs.o
|
||||
-meson-y += meson_viu.o meson_vpp.o meson_venc.o meson_vclk.o meson_canvas.o
|
||||
+meson-drm-y := meson_drv.o meson_plane.o meson_crtc.o meson_venc_cvbs.o
|
||||
+meson-drm-y += meson_viu.o meson_vpp.o meson_venc.o meson_vclk.o meson_canvas.o
|
||||
|
||||
-obj-$(CONFIG_DRM_MESON) += meson.o
|
||||
+obj-$(CONFIG_DRM_MESON) += meson-drm.o
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
From e0f2204f17c247d5e9384d8a57835b480ff16115 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Thu, 2 Feb 2017 10:47:44 +0100
|
||||
Subject: [PATCH 47/93] drm: meson: rename driver name to meson-drm
|
||||
|
||||
The platform driver name is currently "meson" which can lead to some
|
||||
confusion, this patch renames it to "meson-drm" and removes the owner
|
||||
attribute since is always added by __platform_driver_register called by the
|
||||
module_platform_driver() macro.
|
||||
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Acked-by: Daniel Vetter <daniel@ffwll.ch>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/1486028864-19622-3-git-send-email-narmstrong@baylibre.com
|
||||
---
|
||||
drivers/gpu/drm/meson/meson_drv.c | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
|
||||
index ff1f601..380bde7 100644
|
||||
--- a/drivers/gpu/drm/meson/meson_drv.c
|
||||
+++ b/drivers/gpu/drm/meson/meson_drv.c
|
||||
@@ -329,8 +329,7 @@ static int meson_drv_remove(struct platform_device *pdev)
|
||||
.probe = meson_drv_probe,
|
||||
.remove = meson_drv_remove,
|
||||
.driver = {
|
||||
- .owner = THIS_MODULE,
|
||||
- .name = DRIVER_NAME,
|
||||
+ .name = "meson-drm",
|
||||
.of_match_table = dt_match,
|
||||
},
|
||||
};
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
From 1f82a2baa3b5935ed41738f38cf486872aa8a9f7 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Fri, 13 Jan 2017 15:57:10 +0100
|
||||
Subject: [PATCH 48/93] drm/meson: Use crtc_state for hdisplay and fix atomic
|
||||
flush/enable sync for vsync commit
|
||||
|
||||
Clean the crtc_enable by using the proper crtc_state instead of the state
|
||||
of the primary plane state data.
|
||||
|
||||
Also fix the dependency to commit the plane changes even if enable is called
|
||||
after the flush.
|
||||
---
|
||||
drivers/gpu/drm/meson/meson_crtc.c | 15 +++++++++++----
|
||||
1 file changed, 11 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/meson/meson_crtc.c b/drivers/gpu/drm/meson/meson_crtc.c
|
||||
index 749770e..d4b114d 100644
|
||||
--- a/drivers/gpu/drm/meson/meson_crtc.c
|
||||
+++ b/drivers/gpu/drm/meson/meson_crtc.c
|
||||
@@ -60,11 +60,18 @@ struct meson_crtc {
|
||||
static void meson_crtc_enable(struct drm_crtc *crtc)
|
||||
{
|
||||
struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
|
||||
- struct drm_plane *plane = meson_crtc->priv->primary_plane;
|
||||
+ struct drm_crtc_state *crtc_state = crtc->state;
|
||||
struct meson_drm *priv = meson_crtc->priv;
|
||||
|
||||
+ DRM_DEBUG_DRIVER("\n");
|
||||
+
|
||||
+ if (!crtc_state) {
|
||||
+ DRM_ERROR("Invalid crtc_state\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
/* Enable VPP Postblend */
|
||||
- writel(plane->state->crtc_w,
|
||||
+ writel(crtc_state->mode.hdisplay,
|
||||
priv->io_base + _REG(VPP_POSTBLEND_H_SIZE));
|
||||
|
||||
writel_bits_relaxed(VPP_POSTBLEND_ENABLE, VPP_POSTBLEND_ENABLE,
|
||||
@@ -79,6 +86,7 @@ static void meson_crtc_disable(struct drm_crtc *crtc)
|
||||
struct meson_drm *priv = meson_crtc->priv;
|
||||
|
||||
priv->viu.osd1_enabled = false;
|
||||
+ priv->viu.osd1_commit = false;
|
||||
|
||||
/* Disable VPP Postblend */
|
||||
writel_bits_relaxed(VPP_POSTBLEND_ENABLE, 0,
|
||||
@@ -115,8 +123,7 @@ static void meson_crtc_atomic_flush(struct drm_crtc *crtc,
|
||||
struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
|
||||
struct meson_drm *priv = meson_crtc->priv;
|
||||
|
||||
- if (priv->viu.osd1_enabled)
|
||||
- priv->viu.osd1_commit = true;
|
||||
+ priv->viu.osd1_commit = true;
|
||||
}
|
||||
|
||||
static const struct drm_crtc_helper_funcs meson_crtc_helper_funcs = {
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
From aff67758d0ff7e376229fbdc6dc1f92d8e7da770 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Fri, 13 Jan 2017 15:57:38 +0100
|
||||
Subject: [PATCH 49/93] drm/meson: Add missing HDMI register
|
||||
|
||||
Add missing VPU HDMI register.
|
||||
---
|
||||
drivers/gpu/drm/meson/meson_registers.h | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/drivers/gpu/drm/meson/meson_registers.h b/drivers/gpu/drm/meson/meson_registers.h
|
||||
index 6adf9c1..2847381 100644
|
||||
--- a/drivers/gpu/drm/meson/meson_registers.h
|
||||
+++ b/drivers/gpu/drm/meson/meson_registers.h
|
||||
@@ -1319,6 +1319,7 @@
|
||||
#define VPU_MISC_CTRL 0x2740
|
||||
#define VPU_ISP_GCLK_CTRL0 0x2741
|
||||
#define VPU_ISP_GCLK_CTRL1 0x2742
|
||||
+#define VPU_HDMI_FMT_CTRL 0x2743
|
||||
#define VPU_VDIN_ASYNC_HOLD_CTRL 0x2743
|
||||
#define VPU_VDISP_ASYNC_HOLD_CTRL 0x2744
|
||||
#define VPU_VPUARB2_ASYNC_HOLD_CTRL 0x2745
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,191 @@
|
|||
From 5e358cdbdb00b0733e51f29a3f235a3cf3efe159 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Mon, 9 Jan 2017 14:16:44 +0100
|
||||
Subject: [PATCH 50/93] drm/meson: Add support for components
|
||||
|
||||
This patch adds support for optional components connected through the
|
||||
Device Tree endpoints scheme.
|
||||
---
|
||||
drivers/gpu/drm/meson/meson_drv.c | 113 +++++++++++++++++++++++++++++++++-----
|
||||
1 file changed, 99 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
|
||||
index 380bde7..4b506d0 100644
|
||||
--- a/drivers/gpu/drm/meson/meson_drv.c
|
||||
+++ b/drivers/gpu/drm/meson/meson_drv.c
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/platform_device.h>
|
||||
+#include <linux/component.h>
|
||||
#include <linux/of_graph.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
@@ -183,9 +184,9 @@ static bool meson_vpu_has_available_connectors(struct device *dev)
|
||||
.max_register = 0x1000,
|
||||
};
|
||||
|
||||
-static int meson_drv_probe(struct platform_device *pdev)
|
||||
+static int meson_drv_bind(struct device *dev)
|
||||
{
|
||||
- struct device *dev = &pdev->dev;
|
||||
+ struct platform_device *pdev = to_platform_device(dev);
|
||||
struct meson_drm *priv;
|
||||
struct drm_device *drm;
|
||||
struct resource *res;
|
||||
@@ -248,6 +249,15 @@ static int meson_drv_probe(struct platform_device *pdev)
|
||||
|
||||
drm_vblank_init(drm, 1);
|
||||
drm_mode_config_init(drm);
|
||||
+ drm->mode_config.max_width = 3840;
|
||||
+ drm->mode_config.max_height = 2160;
|
||||
+ drm->mode_config.funcs = &meson_mode_config_funcs;
|
||||
+
|
||||
+ /* Hardware Initialization */
|
||||
+
|
||||
+ meson_venc_init(priv);
|
||||
+ meson_vpp_init(priv);
|
||||
+ meson_viu_init(priv);
|
||||
|
||||
/* Encoder Initialization */
|
||||
|
||||
@@ -255,11 +265,11 @@ static int meson_drv_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
goto free_drm;
|
||||
|
||||
- /* Hardware Initialization */
|
||||
-
|
||||
- meson_venc_init(priv);
|
||||
- meson_vpp_init(priv);
|
||||
- meson_viu_init(priv);
|
||||
+ ret = component_bind_all(drm->dev, drm);
|
||||
+ if (ret) {
|
||||
+ dev_err(drm->dev, "Couldn't bind all components\n");
|
||||
+ goto free_drm;
|
||||
+ }
|
||||
|
||||
ret = meson_plane_create(priv);
|
||||
if (ret)
|
||||
@@ -274,9 +284,6 @@ static int meson_drv_probe(struct platform_device *pdev)
|
||||
goto free_drm;
|
||||
|
||||
drm_mode_config_reset(drm);
|
||||
- drm->mode_config.max_width = 8192;
|
||||
- drm->mode_config.max_height = 8192;
|
||||
- drm->mode_config.funcs = &meson_mode_config_funcs;
|
||||
|
||||
priv->fbdev = drm_fbdev_cma_init(drm, 32,
|
||||
drm->mode_config.num_crtc,
|
||||
@@ -302,9 +309,9 @@ static int meson_drv_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static int meson_drv_remove(struct platform_device *pdev)
|
||||
+static void meson_drv_unbind(struct device *dev)
|
||||
{
|
||||
- struct drm_device *drm = dev_get_drvdata(&pdev->dev);
|
||||
+ struct drm_device *drm = dev_get_drvdata(dev);
|
||||
struct meson_drm *priv = drm->dev_private;
|
||||
|
||||
drm_dev_unregister(drm);
|
||||
@@ -314,9 +321,88 @@ static int meson_drv_remove(struct platform_device *pdev)
|
||||
drm_vblank_cleanup(drm);
|
||||
drm_dev_unref(drm);
|
||||
|
||||
- return 0;
|
||||
}
|
||||
|
||||
+static const struct component_master_ops meson_drv_master_ops = {
|
||||
+ .bind = meson_drv_bind,
|
||||
+ .unbind = meson_drv_unbind,
|
||||
+};
|
||||
+
|
||||
+static int compare_of(struct device *dev, void *data)
|
||||
+{
|
||||
+ DRM_DEBUG_DRIVER("Comparing of node %s with %s\n",
|
||||
+ of_node_full_name(dev->of_node),
|
||||
+ of_node_full_name(data));
|
||||
+
|
||||
+ return dev->of_node == data;
|
||||
+}
|
||||
+
|
||||
+/* Possible connectors nodes to ignore */
|
||||
+static const struct of_device_id connectors_match[] = {
|
||||
+ { .compatible = "composite-video-connector" },
|
||||
+ { .compatible = "svideo-connector" },
|
||||
+ { .compatible = "hdmi-connector" },
|
||||
+ { .compatible = "dvi-connector" },
|
||||
+ {}
|
||||
+};
|
||||
+
|
||||
+static int meson_probe_remote(struct platform_device *pdev,
|
||||
+ struct component_match **match,
|
||||
+ struct device_node *parent,
|
||||
+ struct device_node *remote)
|
||||
+{
|
||||
+ struct device_node *ep, *remote_node;
|
||||
+ int count = 1;
|
||||
+
|
||||
+ /* If node is a connector, return and do not add to match table */
|
||||
+ if (of_match_node(connectors_match, remote))
|
||||
+ return 1;
|
||||
+
|
||||
+ component_match_add(&pdev->dev, match, compare_of, remote);
|
||||
+
|
||||
+ for_each_endpoint_of_node(remote, ep) {
|
||||
+ remote_node = of_graph_get_remote_port_parent(ep);
|
||||
+ if (!remote_node ||
|
||||
+ remote_node == parent || /* Ignore parent endpoint */
|
||||
+ !of_device_is_available(remote_node))
|
||||
+ continue;
|
||||
+
|
||||
+ count += meson_probe_remote(pdev, match, remote, remote_node);
|
||||
+
|
||||
+ of_node_put(remote_node);
|
||||
+ }
|
||||
+
|
||||
+ return count;
|
||||
+}
|
||||
+
|
||||
+static int meson_drv_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct component_match *match = NULL;
|
||||
+ struct device_node *np = pdev->dev.of_node;
|
||||
+ struct device_node *ep, *remote;
|
||||
+ int count = 0;
|
||||
+
|
||||
+ for_each_endpoint_of_node(np, ep) {
|
||||
+ remote = of_graph_get_remote_port_parent(ep);
|
||||
+ if (!remote || !of_device_is_available(remote))
|
||||
+ continue;
|
||||
+
|
||||
+ count += meson_probe_remote(pdev, &match, np, remote);
|
||||
+ }
|
||||
+
|
||||
+ /* If some endpoints were found, initialize the nodes */
|
||||
+ if (count) {
|
||||
+ dev_info(&pdev->dev, "Queued %d outputs on vpu\n", count);
|
||||
+
|
||||
+ return component_master_add_with_match(&pdev->dev,
|
||||
+ &meson_drv_master_ops,
|
||||
+ match);
|
||||
+ }
|
||||
+
|
||||
+ /* If no output endpoints were available, simply bail out */
|
||||
+ return 0;
|
||||
+};
|
||||
+
|
||||
static const struct of_device_id dt_match[] = {
|
||||
{ .compatible = "amlogic,meson-gxbb-vpu" },
|
||||
{ .compatible = "amlogic,meson-gxl-vpu" },
|
||||
@@ -327,7 +413,6 @@ static int meson_drv_remove(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver meson_drm_platform_driver = {
|
||||
.probe = meson_drv_probe,
|
||||
- .remove = meson_drv_remove,
|
||||
.driver = {
|
||||
.name = "meson-drm",
|
||||
.of_match_table = dt_match,
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
From 59e092e2793539ce5fe61e4e8a40732e9c76f744 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Thu, 9 Feb 2017 11:37:27 +0100
|
||||
Subject: [PATCH 51/93] drm/meson: venc_cvbs: no more return -ENODEV if CVBS is
|
||||
not available
|
||||
|
||||
Since this is managed now by the components code, if CVBS is not available
|
||||
and HDMI neither, the drm driver won't bind anyway.
|
||||
---
|
||||
drivers/gpu/drm/meson/meson_venc_cvbs.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/meson/meson_venc_cvbs.c b/drivers/gpu/drm/meson/meson_venc_cvbs.c
|
||||
index a2bcc70..a96fcb4 100644
|
||||
--- a/drivers/gpu/drm/meson/meson_venc_cvbs.c
|
||||
+++ b/drivers/gpu/drm/meson/meson_venc_cvbs.c
|
||||
@@ -248,7 +248,7 @@ int meson_venc_cvbs_create(struct meson_drm *priv)
|
||||
|
||||
if (!meson_venc_cvbs_connector_is_available(priv)) {
|
||||
dev_info(drm->dev, "CVBS Output connector not available\n");
|
||||
- return -ENODEV;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
meson_venc_cvbs = devm_kzalloc(priv->dev, sizeof(*meson_venc_cvbs),
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,740 @@
|
|||
From 336d370ab9227e29eedd829e7f88a7ace9241298 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Mon, 9 Jan 2017 14:18:36 +0100
|
||||
Subject: [PATCH 52/93] drm/meson: add support for HDMI clock support
|
||||
|
||||
This patchs adds support for the supported HDMI modes clocks frequencies.
|
||||
---
|
||||
drivers/gpu/drm/meson/meson_vclk.c | 624 +++++++++++++++++++++++++++++++-
|
||||
drivers/gpu/drm/meson/meson_vclk.h | 6 +-
|
||||
drivers/gpu/drm/meson/meson_venc_cvbs.c | 9 +-
|
||||
3 files changed, 623 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c
|
||||
index 252cfd4..3731479 100644
|
||||
--- a/drivers/gpu/drm/meson/meson_vclk.c
|
||||
+++ b/drivers/gpu/drm/meson/meson_vclk.c
|
||||
@@ -27,9 +27,26 @@
|
||||
* VCLK is the "Pixel Clock" frequency generator from a dedicated PLL.
|
||||
* We handle the following encodings :
|
||||
* - CVBS 27MHz generator via the VCLK2 to the VENCI and VDAC blocks
|
||||
- *
|
||||
- * What is missing :
|
||||
* - HDMI Pixel Clocks generation
|
||||
+ * What is missing :
|
||||
+ * - Genenate Pixel clocks for 2K/4K 10bit formats
|
||||
+ *
|
||||
+ * Clock generator scheme :
|
||||
+ * __________ _________ _____
|
||||
+ * | | | | | |--ENCI
|
||||
+ * | HDMI PLL |-| PLL_DIV |--- VCLK--| |--ENCL
|
||||
+ * |__________| |_________| \ | MUX |--ENCP
|
||||
+ * --VCLK2-| |--VDAC
|
||||
+ * |_____|--HDMI-TX
|
||||
+ *
|
||||
+ * Final clocks can take input for either VCLK or VCLK2, but
|
||||
+ * VCLK is the preferred path for HDMI clocking and VCLK2 is the
|
||||
+ * preferred path for CVBS VDAC clocking.
|
||||
+ *
|
||||
+ * VCLK and VCLK2 have fixed divided clocks paths for /1, /2, /4, /6 or /12.
|
||||
+ *
|
||||
+ * The PLL_DIV can achieve an additional fractional dividing like
|
||||
+ * 1.5, 3.5, 3.75... to generate special 2K and 4K 10bit clocks.
|
||||
*/
|
||||
|
||||
/* HHI Registers */
|
||||
@@ -50,11 +67,34 @@
|
||||
#define VCLK2_SOFT_RESET BIT(15)
|
||||
#define VCLK2_DIV1_EN BIT(0)
|
||||
#define HHI_VID_CLK_DIV 0x164 /* 0x59 offset in data sheet */
|
||||
+#define VCLK_DIV_MASK 0xff
|
||||
+#define VCLK_DIV_EN BIT(16)
|
||||
+#define VCLK_DIV_RESET BIT(17)
|
||||
+#define CTS_ENCP_SEL_MASK (0xf << 24)
|
||||
+#define CTS_ENCP_SEL_SHIFT 24
|
||||
#define CTS_ENCI_SEL_MASK (0xf << 28)
|
||||
#define CTS_ENCI_SEL_SHIFT 28
|
||||
+#define HHI_VID_CLK_CNTL 0x17c /* 0x5f offset in data sheet */
|
||||
+#define VCLK_EN BIT(19)
|
||||
+#define VCLK_SEL_MASK (0x7 << 16)
|
||||
+#define VCLK_SEL_SHIFT 16
|
||||
+#define VCLK_SOFT_RESET BIT(15)
|
||||
+#define VCLK_DIV1_EN BIT(0)
|
||||
+#define VCLK_DIV2_EN BIT(1)
|
||||
+#define VCLK_DIV4_EN BIT(2)
|
||||
+#define VCLK_DIV6_EN BIT(3)
|
||||
+#define VCLK_DIV12_EN BIT(4)
|
||||
#define HHI_VID_CLK_CNTL2 0x194 /* 0x65 offset in data sheet */
|
||||
#define CTS_ENCI_EN BIT(0)
|
||||
+#define CTS_ENCP_EN BIT(2)
|
||||
#define CTS_VDAC_EN BIT(4)
|
||||
+#define HDMI_TX_PIXEL_EN BIT(5)
|
||||
+#define HHI_HDMI_CLK_CNTL 0x1cc /* 0x73 offset in data sheet */
|
||||
+#define HDMI_TX_PIXEL_SEL_MASK (0xf << 16)
|
||||
+#define HDMI_TX_PIXEL_SEL_SHIFT 16
|
||||
+#define CTS_HDMI_SYS_SEL_MASK (0x7 << 9)
|
||||
+#define CTS_HDMI_SYS_DIV_MASK (0x7f)
|
||||
+#define CTS_HDMI_SYS_EN BIT(8)
|
||||
|
||||
#define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */
|
||||
#define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */
|
||||
@@ -69,6 +109,126 @@
|
||||
#define HDMI_PLL_RESET BIT(28)
|
||||
#define HDMI_PLL_LOCK BIT(31)
|
||||
|
||||
+/* VID PLL Dividers */
|
||||
+enum {
|
||||
+ VID_PLL_DIV_1 = 0,
|
||||
+ VID_PLL_DIV_2,
|
||||
+ VID_PLL_DIV_2p5,
|
||||
+ VID_PLL_DIV_3,
|
||||
+ VID_PLL_DIV_3p5,
|
||||
+ VID_PLL_DIV_3p75,
|
||||
+ VID_PLL_DIV_4,
|
||||
+ VID_PLL_DIV_5,
|
||||
+ VID_PLL_DIV_6,
|
||||
+ VID_PLL_DIV_6p25,
|
||||
+ VID_PLL_DIV_7,
|
||||
+ VID_PLL_DIV_7p5,
|
||||
+ VID_PLL_DIV_12,
|
||||
+ VID_PLL_DIV_14,
|
||||
+ VID_PLL_DIV_15,
|
||||
+};
|
||||
+
|
||||
+void meson_vid_pll_set(struct meson_drm *priv, unsigned int div)
|
||||
+{
|
||||
+ unsigned int shift_val = 0;
|
||||
+ unsigned int shift_sel = 0;
|
||||
+
|
||||
+ /* Disable vid_pll output clock */
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, VID_PLL_EN, 0);
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, VID_PLL_PRESET, 0);
|
||||
+
|
||||
+ switch (div) {
|
||||
+ case VID_PLL_DIV_2:
|
||||
+ shift_val = 0x0aaa;
|
||||
+ shift_sel = 0;
|
||||
+ break;
|
||||
+ case VID_PLL_DIV_2p5:
|
||||
+ shift_val = 0x5294;
|
||||
+ shift_sel = 2;
|
||||
+ break;
|
||||
+ case VID_PLL_DIV_3:
|
||||
+ shift_val = 0x0db6;
|
||||
+ shift_sel = 0;
|
||||
+ break;
|
||||
+ case VID_PLL_DIV_3p5:
|
||||
+ shift_val = 0x36cc;
|
||||
+ shift_sel = 1;
|
||||
+ break;
|
||||
+ case VID_PLL_DIV_3p75:
|
||||
+ shift_val = 0x6666;
|
||||
+ shift_sel = 2;
|
||||
+ break;
|
||||
+ case VID_PLL_DIV_4:
|
||||
+ shift_val = 0x0ccc;
|
||||
+ shift_sel = 0;
|
||||
+ break;
|
||||
+ case VID_PLL_DIV_5:
|
||||
+ shift_val = 0x739c;
|
||||
+ shift_sel = 2;
|
||||
+ break;
|
||||
+ case VID_PLL_DIV_6:
|
||||
+ shift_val = 0x0e38;
|
||||
+ shift_sel = 0;
|
||||
+ break;
|
||||
+ case VID_PLL_DIV_6p25:
|
||||
+ shift_val = 0x0000;
|
||||
+ shift_sel = 3;
|
||||
+ break;
|
||||
+ case VID_PLL_DIV_7:
|
||||
+ shift_val = 0x3c78;
|
||||
+ shift_sel = 1;
|
||||
+ break;
|
||||
+ case VID_PLL_DIV_7p5:
|
||||
+ shift_val = 0x78f0;
|
||||
+ shift_sel = 2;
|
||||
+ break;
|
||||
+ case VID_PLL_DIV_12:
|
||||
+ shift_val = 0x0fc0;
|
||||
+ shift_sel = 0;
|
||||
+ break;
|
||||
+ case VID_PLL_DIV_14:
|
||||
+ shift_val = 0x3f80;
|
||||
+ shift_sel = 1;
|
||||
+ break;
|
||||
+ case VID_PLL_DIV_15:
|
||||
+ shift_val = 0x7f80;
|
||||
+ shift_sel = 2;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (div == VID_PLL_DIV_1)
|
||||
+ /* Enable vid_pll bypass to HDMI pll */
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
|
||||
+ VID_PLL_BYPASS, VID_PLL_BYPASS);
|
||||
+ else {
|
||||
+ /* Disable Bypass */
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
|
||||
+ VID_PLL_BYPASS, 0);
|
||||
+ /* Clear sel */
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
|
||||
+ 3 << 16, 0);
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
|
||||
+ VID_PLL_PRESET, 0);
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
|
||||
+ 0x7fff, 0);
|
||||
+
|
||||
+ /* Setup sel and val */
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
|
||||
+ 3 << 16, shift_sel << 16);
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
|
||||
+ VID_PLL_PRESET, VID_PLL_PRESET);
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
|
||||
+ 0x7fff, shift_val);
|
||||
+
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
|
||||
+ VID_PLL_PRESET, 0);
|
||||
+ }
|
||||
+
|
||||
+ /* Enable the vid_pll output clock */
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
|
||||
+ VID_PLL_EN, VID_PLL_EN);
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Setup VCLK2 for 27MHz, and enable clocks for ENCI and VDAC
|
||||
*
|
||||
@@ -110,15 +270,8 @@ static void meson_venci_cvbs_clock_config(struct meson_drm *priv)
|
||||
/* Disable VCLK2 */
|
||||
regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, 0);
|
||||
|
||||
- /* Disable vid_pll output clock */
|
||||
- regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, VID_PLL_EN, 0);
|
||||
- regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, VID_PLL_PRESET, 0);
|
||||
- /* Enable vid_pll bypass to HDMI pll */
|
||||
- regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
|
||||
- VID_PLL_BYPASS, VID_PLL_BYPASS);
|
||||
- /* Enable the vid_pll output clock */
|
||||
- regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
|
||||
- VID_PLL_EN, VID_PLL_EN);
|
||||
+ /* Setup vid_pll to /1 */
|
||||
+ meson_vid_pll_set(priv, VID_PLL_DIV_1);
|
||||
|
||||
/* Setup the VCLK2 divider value to achieve 27MHz */
|
||||
regmap_update_bits(priv->hhi, HHI_VIID_CLK_DIV,
|
||||
@@ -159,9 +312,454 @@ static void meson_venci_cvbs_clock_config(struct meson_drm *priv)
|
||||
CTS_VDAC_EN, CTS_VDAC_EN);
|
||||
}
|
||||
|
||||
+
|
||||
+/* PLL O1 O2 O3 VP DV EN TX */
|
||||
+/* 4320 /4 /4 /1 /5 /1 => /2 /2 */
|
||||
+#define MESON_VCLK_HDMI_ENCI_54000 1
|
||||
+/* 4320 /4 /4 /1 /5 /1 => /1 /2 */
|
||||
+#define MESON_VCLK_HDMI_DDR_54000 2
|
||||
+/* 2970 /4 /1 /1 /5 /1 => /1 /2 */
|
||||
+#define MESON_VCLK_HDMI_DDR_148500 3
|
||||
+/* 2970 /2 /2 /2 /5 /1 => /1 /1 */
|
||||
+#define MESON_VCLK_HDMI_74250 4
|
||||
+/* 2970 /1 /2 /2 /5 /1 => /1 /1 */
|
||||
+#define MESON_VCLK_HDMI_148500 5
|
||||
+/* 2970 /1 /1 /1 /5 /2 => /1 /1 */
|
||||
+#define MESON_VCLK_HDMI_297000 6
|
||||
+/* 5940 /1 /1 /2 /5 /1 => /1 /1 */
|
||||
+#define MESON_VCLK_HDMI_594000 7
|
||||
+
|
||||
+struct meson_vclk_params {
|
||||
+ unsigned int pll_base_freq;
|
||||
+ unsigned int pll_od1;
|
||||
+ unsigned int pll_od2;
|
||||
+ unsigned int pll_od3;
|
||||
+ unsigned int vid_pll_div;
|
||||
+ unsigned int vclk_div;
|
||||
+} params[] = {
|
||||
+ [MESON_VCLK_HDMI_ENCI_54000] = {
|
||||
+ .pll_base_freq = 4320000,
|
||||
+ .pll_od1 = 4,
|
||||
+ .pll_od2 = 4,
|
||||
+ .pll_od3 = 1,
|
||||
+ .vid_pll_div = VID_PLL_DIV_5,
|
||||
+ .vclk_div = 1,
|
||||
+ },
|
||||
+ [MESON_VCLK_HDMI_DDR_54000] = {
|
||||
+ .pll_base_freq = 4320000,
|
||||
+ .pll_od1 = 4,
|
||||
+ .pll_od2 = 4,
|
||||
+ .pll_od3 = 1,
|
||||
+ .vid_pll_div = VID_PLL_DIV_5,
|
||||
+ .vclk_div = 1,
|
||||
+ },
|
||||
+ [MESON_VCLK_HDMI_DDR_148500] = {
|
||||
+ .pll_base_freq = 2970000,
|
||||
+ .pll_od1 = 4,
|
||||
+ .pll_od2 = 1,
|
||||
+ .pll_od3 = 1,
|
||||
+ .vid_pll_div = VID_PLL_DIV_5,
|
||||
+ .vclk_div = 1,
|
||||
+ },
|
||||
+ [MESON_VCLK_HDMI_74250] = {
|
||||
+ .pll_base_freq = 2970000,
|
||||
+ .pll_od1 = 2,
|
||||
+ .pll_od2 = 2,
|
||||
+ .pll_od3 = 2,
|
||||
+ .vid_pll_div = VID_PLL_DIV_5,
|
||||
+ .vclk_div = 1,
|
||||
+ },
|
||||
+ [MESON_VCLK_HDMI_148500] = {
|
||||
+ .pll_base_freq = 2970000,
|
||||
+ .pll_od1 = 1,
|
||||
+ .pll_od2 = 2,
|
||||
+ .pll_od3 = 2,
|
||||
+ .vid_pll_div = VID_PLL_DIV_5,
|
||||
+ .vclk_div = 1,
|
||||
+ },
|
||||
+ [MESON_VCLK_HDMI_297000] = {
|
||||
+ .pll_base_freq = 2970000,
|
||||
+ .pll_od1 = 1,
|
||||
+ .pll_od2 = 1,
|
||||
+ .pll_od3 = 1,
|
||||
+ .vid_pll_div = VID_PLL_DIV_5,
|
||||
+ .vclk_div = 2,
|
||||
+ },
|
||||
+ [MESON_VCLK_HDMI_594000] = {
|
||||
+ .pll_base_freq = 5940000,
|
||||
+ .pll_od1 = 1,
|
||||
+ .pll_od2 = 1,
|
||||
+ .pll_od3 = 2,
|
||||
+ .vid_pll_div = VID_PLL_DIV_5,
|
||||
+ .vclk_div = 1,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static inline unsigned int pll_od_to_reg(unsigned int od)
|
||||
+{
|
||||
+ switch (od) {
|
||||
+ case 1:
|
||||
+ return 0;
|
||||
+ case 2:
|
||||
+ return 1;
|
||||
+ case 4:
|
||||
+ return 2;
|
||||
+ case 8:
|
||||
+ return 3;
|
||||
+ }
|
||||
+
|
||||
+ /* Invalid */
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+void meson_hdmi_pll_set(struct meson_drm *priv,
|
||||
+ unsigned int base,
|
||||
+ unsigned int od1,
|
||||
+ unsigned int od2,
|
||||
+ unsigned int od3)
|
||||
+{
|
||||
+ unsigned int val;
|
||||
+
|
||||
+ if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) {
|
||||
+ switch (base) {
|
||||
+ case 2970000:
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x5800023d);
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000);
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
|
||||
+
|
||||
+ /* Enable and unreset */
|
||||
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
|
||||
+ 0x7 << 28, 0x4 << 28);
|
||||
+
|
||||
+ /* Poll for lock bit */
|
||||
+ regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
|
||||
+ val, (val & HDMI_PLL_LOCK), 10, 0);
|
||||
+
|
||||
+ /* div_frac */
|
||||
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
|
||||
+ 0xFFFF, 0x4e00);
|
||||
+ break;
|
||||
+
|
||||
+ case 4320000:
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x5800025a);
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000);
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
|
||||
+
|
||||
+ /* unreset */
|
||||
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
|
||||
+ BIT(28), 0);
|
||||
+
|
||||
+ /* Poll for lock bit */
|
||||
+ regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
|
||||
+ val, (val & HDMI_PLL_LOCK), 10, 0);
|
||||
+ break;
|
||||
+
|
||||
+ case 5940000:
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x5800027b);
|
||||
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
|
||||
+ 0xFFFF, 0x4c00);
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x135c5091);
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
|
||||
+
|
||||
+ /* unreset */
|
||||
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
|
||||
+ BIT(28), 0);
|
||||
+
|
||||
+ /* Poll for lock bit */
|
||||
+ regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
|
||||
+ val, (val & HDMI_PLL_LOCK), 10, 0);
|
||||
+ break;
|
||||
+ };
|
||||
+ } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
|
||||
+ meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) {
|
||||
+ switch (base) {
|
||||
+ case 2970000:
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x4000027b);
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb300);
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4);
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
|
||||
+ break;
|
||||
+
|
||||
+ case 4320000:
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x400002b4);
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb000);
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4);
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
|
||||
+ break;
|
||||
+
|
||||
+ case 5940000:
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x400002f7);
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb200);
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4);
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
|
||||
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
|
||||
+ break;
|
||||
+
|
||||
+ };
|
||||
+
|
||||
+ /* Reset PLL */
|
||||
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
|
||||
+ HDMI_PLL_RESET, HDMI_PLL_RESET);
|
||||
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
|
||||
+ HDMI_PLL_RESET, 0);
|
||||
+
|
||||
+ /* Poll for lock bit */
|
||||
+ regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
|
||||
+ (val & HDMI_PLL_LOCK), 10, 0);
|
||||
+ };
|
||||
+
|
||||
+ if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
|
||||
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
|
||||
+ 3 << 16, pll_od_to_reg(od1) << 16);
|
||||
+ else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
|
||||
+ meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
|
||||
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
|
||||
+ 3 << 21, pll_od_to_reg(od1) << 21);
|
||||
+
|
||||
+ if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
|
||||
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
|
||||
+ 3 << 22, pll_od_to_reg(od2) << 22);
|
||||
+ else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
|
||||
+ meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
|
||||
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
|
||||
+ 3 << 23, pll_od_to_reg(od2) << 23);
|
||||
+
|
||||
+ if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
|
||||
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
|
||||
+ 3 << 18, pll_od_to_reg(od3) << 18);
|
||||
+ else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
|
||||
+ meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
|
||||
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
|
||||
+ 3 << 19, pll_od_to_reg(od3) << 19);
|
||||
+}
|
||||
+
|
||||
void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
|
||||
- unsigned int freq)
|
||||
+ unsigned int vclk_freq, unsigned int venc_freq,
|
||||
+ unsigned int dac_freq, bool hdmi_use_enci)
|
||||
{
|
||||
- if (target == MESON_VCLK_TARGET_CVBS && freq == MESON_VCLK_CVBS)
|
||||
+ unsigned int freq;
|
||||
+ unsigned int hdmi_tx_div;
|
||||
+ unsigned int venc_div;
|
||||
+
|
||||
+ if (target == MESON_VCLK_TARGET_CVBS) {
|
||||
meson_venci_cvbs_clock_config(priv);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ hdmi_tx_div = vclk_freq / dac_freq;
|
||||
+
|
||||
+ if (hdmi_tx_div == 0) {
|
||||
+ pr_err("Fatal Error, invalid HDMI-TX freq %d\n",
|
||||
+ dac_freq);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ venc_div = vclk_freq / venc_freq;
|
||||
+
|
||||
+ if (venc_div == 0) {
|
||||
+ pr_err("Fatal Error, invalid HDMI venc freq %d\n",
|
||||
+ venc_freq);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ switch (vclk_freq) {
|
||||
+ case 54000:
|
||||
+ if (hdmi_use_enci)
|
||||
+ freq = MESON_VCLK_HDMI_ENCI_54000;
|
||||
+ else
|
||||
+ freq = MESON_VCLK_HDMI_DDR_54000;
|
||||
+ break;
|
||||
+ case 74250:
|
||||
+ freq = MESON_VCLK_HDMI_74250;
|
||||
+ break;
|
||||
+ case 148500:
|
||||
+ if (dac_freq != 148500)
|
||||
+ freq = MESON_VCLK_HDMI_DDR_148500;
|
||||
+ else
|
||||
+ freq = MESON_VCLK_HDMI_148500;
|
||||
+ break;
|
||||
+ case 297000:
|
||||
+ freq = MESON_VCLK_HDMI_297000;
|
||||
+ break;
|
||||
+ case 594000:
|
||||
+ freq = MESON_VCLK_HDMI_594000;
|
||||
+ break;
|
||||
+ default:
|
||||
+ pr_err("Fatal Error, invalid HDMI vclk freq %d\n",
|
||||
+ vclk_freq);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* Set HDMI-TX sys clock */
|
||||
+ regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
|
||||
+ CTS_HDMI_SYS_SEL_MASK, 0);
|
||||
+ regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
|
||||
+ CTS_HDMI_SYS_DIV_MASK, 0);
|
||||
+ regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
|
||||
+ CTS_HDMI_SYS_EN, CTS_HDMI_SYS_EN);
|
||||
+
|
||||
+ /* Set HDMI PLL rate */
|
||||
+ meson_hdmi_pll_set(priv, params[freq].pll_base_freq,
|
||||
+ params[freq].pll_od1,
|
||||
+ params[freq].pll_od2,
|
||||
+ params[freq].pll_od3);
|
||||
+
|
||||
+ /* Setup vid_pll divider */
|
||||
+ meson_vid_pll_set(priv, params[freq].vid_pll_div);
|
||||
+
|
||||
+ /* Set VCLK div */
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
|
||||
+ VCLK_SEL_MASK, 0);
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
|
||||
+ VCLK_DIV_MASK, params[freq].vclk_div - 1);
|
||||
+
|
||||
+ /* Set HDMI-TX source */
|
||||
+ switch (hdmi_tx_div) {
|
||||
+ case 1:
|
||||
+ /* enable vclk_div1 gate */
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
|
||||
+ VCLK_DIV1_EN, VCLK_DIV1_EN);
|
||||
+
|
||||
+ /* select vclk_div1 for HDMI-TX */
|
||||
+ regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
|
||||
+ HDMI_TX_PIXEL_SEL_MASK, 0);
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ /* enable vclk_div2 gate */
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
|
||||
+ VCLK_DIV2_EN, VCLK_DIV2_EN);
|
||||
+
|
||||
+ /* select vclk_div2 for HDMI-TX */
|
||||
+ regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
|
||||
+ HDMI_TX_PIXEL_SEL_MASK, 1 << HDMI_TX_PIXEL_SEL_SHIFT);
|
||||
+ break;
|
||||
+ case 4:
|
||||
+ /* enable vclk_div4 gate */
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
|
||||
+ VCLK_DIV4_EN, VCLK_DIV4_EN);
|
||||
+
|
||||
+ /* select vclk_div4 for HDMI-TX */
|
||||
+ regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
|
||||
+ HDMI_TX_PIXEL_SEL_MASK, 2 << HDMI_TX_PIXEL_SEL_SHIFT);
|
||||
+ break;
|
||||
+ case 6:
|
||||
+ /* enable vclk_div6 gate */
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
|
||||
+ VCLK_DIV6_EN, VCLK_DIV6_EN);
|
||||
+
|
||||
+ /* select vclk_div6 for HDMI-TX */
|
||||
+ regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
|
||||
+ HDMI_TX_PIXEL_SEL_MASK, 3 << HDMI_TX_PIXEL_SEL_SHIFT);
|
||||
+ break;
|
||||
+ case 12:
|
||||
+ /* enable vclk_div12 gate */
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
|
||||
+ VCLK_DIV12_EN, VCLK_DIV12_EN);
|
||||
+
|
||||
+ /* select vclk_div12 for HDMI-TX */
|
||||
+ regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
|
||||
+ HDMI_TX_PIXEL_SEL_MASK, 4 << HDMI_TX_PIXEL_SEL_SHIFT);
|
||||
+ break;
|
||||
+ }
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
|
||||
+ HDMI_TX_PIXEL_EN, HDMI_TX_PIXEL_EN);
|
||||
+
|
||||
+ /* Set ENCI/ENCP Source */
|
||||
+ switch (venc_div) {
|
||||
+ case 1:
|
||||
+ /* enable vclk_div1 gate */
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
|
||||
+ VCLK_DIV1_EN, VCLK_DIV1_EN);
|
||||
+
|
||||
+ if (hdmi_use_enci)
|
||||
+ /* select vclk_div1 for enci */
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
|
||||
+ CTS_ENCI_SEL_MASK, 0);
|
||||
+ else
|
||||
+ /* select vclk_div1 for encp */
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
|
||||
+ CTS_ENCP_SEL_MASK, 0);
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ /* enable vclk_div2 gate */
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
|
||||
+ VCLK_DIV2_EN, VCLK_DIV2_EN);
|
||||
+
|
||||
+ if (hdmi_use_enci)
|
||||
+ /* select vclk_div2 for enci */
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
|
||||
+ CTS_ENCI_SEL_MASK, 1 << CTS_ENCI_SEL_SHIFT);
|
||||
+ else
|
||||
+ /* select vclk_div2 for encp */
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
|
||||
+ CTS_ENCP_SEL_MASK, 1 << CTS_ENCP_SEL_SHIFT);
|
||||
+ break;
|
||||
+ case 4:
|
||||
+ /* enable vclk_div4 gate */
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
|
||||
+ VCLK_DIV4_EN, VCLK_DIV4_EN);
|
||||
+
|
||||
+ if (hdmi_use_enci)
|
||||
+ /* select vclk_div4 for enci */
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
|
||||
+ CTS_ENCI_SEL_MASK, 2 << CTS_ENCI_SEL_SHIFT);
|
||||
+ else
|
||||
+ /* select vclk_div4 for encp */
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
|
||||
+ CTS_ENCP_SEL_MASK, 2 << CTS_ENCP_SEL_SHIFT);
|
||||
+ break;
|
||||
+ case 6:
|
||||
+ /* enable vclk_div6 gate */
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
|
||||
+ VCLK_DIV6_EN, VCLK_DIV6_EN);
|
||||
+
|
||||
+ if (hdmi_use_enci)
|
||||
+ /* select vclk_div6 for enci */
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
|
||||
+ CTS_ENCI_SEL_MASK, 3 << CTS_ENCI_SEL_SHIFT);
|
||||
+ else
|
||||
+ /* select vclk_div6 for encp */
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
|
||||
+ CTS_ENCP_SEL_MASK, 3 << CTS_ENCP_SEL_SHIFT);
|
||||
+ break;
|
||||
+ case 12:
|
||||
+ /* enable vclk_div12 gate */
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
|
||||
+ VCLK_DIV12_EN, VCLK_DIV12_EN);
|
||||
+
|
||||
+ if (hdmi_use_enci)
|
||||
+ /* select vclk_div12 for enci */
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
|
||||
+ CTS_ENCI_SEL_MASK, 4 << CTS_ENCI_SEL_SHIFT);
|
||||
+ else
|
||||
+ /* select vclk_div12 for encp */
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
|
||||
+ CTS_ENCP_SEL_MASK, 4 << CTS_ENCP_SEL_SHIFT);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (hdmi_use_enci)
|
||||
+ /* Enable ENCI clock gate */
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
|
||||
+ CTS_ENCI_EN, CTS_ENCI_EN);
|
||||
+ else
|
||||
+ /* Enable ENCP clock gate */
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
|
||||
+ CTS_ENCP_EN, CTS_ENCP_EN);
|
||||
+
|
||||
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL, VCLK_EN, VCLK_EN);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(meson_vclk_setup);
|
||||
diff --git a/drivers/gpu/drm/meson/meson_vclk.h b/drivers/gpu/drm/meson/meson_vclk.h
|
||||
index ec62735..0401b52 100644
|
||||
--- a/drivers/gpu/drm/meson/meson_vclk.h
|
||||
+++ b/drivers/gpu/drm/meson/meson_vclk.h
|
||||
@@ -23,12 +23,14 @@
|
||||
|
||||
enum {
|
||||
MESON_VCLK_TARGET_CVBS = 0,
|
||||
+ MESON_VCLK_TARGET_HDMI = 1,
|
||||
};
|
||||
|
||||
/* 27MHz is the CVBS Pixel Clock */
|
||||
-#define MESON_VCLK_CVBS 27000
|
||||
+#define MESON_VCLK_CVBS 27000
|
||||
|
||||
void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
|
||||
- unsigned int freq);
|
||||
+ unsigned int vclk_freq, unsigned int venc_freq,
|
||||
+ unsigned int dac_freq, bool hdmi_use_enci);
|
||||
|
||||
#endif /* __MESON_VCLK_H */
|
||||
diff --git a/drivers/gpu/drm/meson/meson_venc_cvbs.c b/drivers/gpu/drm/meson/meson_venc_cvbs.c
|
||||
index a96fcb4..5d4f19a 100644
|
||||
--- a/drivers/gpu/drm/meson/meson_venc_cvbs.c
|
||||
+++ b/drivers/gpu/drm/meson/meson_venc_cvbs.c
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#include "meson_venc_cvbs.h"
|
||||
#include "meson_venc.h"
|
||||
+#include "meson_vclk.h"
|
||||
#include "meson_registers.h"
|
||||
|
||||
/* HHI VDAC Registers */
|
||||
@@ -194,14 +195,20 @@ static void meson_venc_cvbs_encoder_mode_set(struct drm_encoder *encoder,
|
||||
{
|
||||
struct meson_venc_cvbs *meson_venc_cvbs =
|
||||
encoder_to_meson_venc_cvbs(encoder);
|
||||
+ struct meson_drm *priv = meson_venc_cvbs->priv;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) {
|
||||
struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i];
|
||||
|
||||
if (drm_mode_equal(mode, &meson_mode->mode)) {
|
||||
- meson_venci_cvbs_mode_set(meson_venc_cvbs->priv,
|
||||
+ meson_venci_cvbs_mode_set(priv,
|
||||
meson_mode->enci);
|
||||
+
|
||||
+ /* Setup 27MHz vclk2 for ENCI and VDAC */
|
||||
+ meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS,
|
||||
+ MESON_VCLK_CVBS, MESON_VCLK_CVBS,
|
||||
+ MESON_VCLK_CVBS, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
--
|
||||
1.9.1
|
||||
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,250 @@
|
|||
From f2dfb958c4d11d201619c9f5568de783c87d7ea0 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Fri, 3 Mar 2017 11:02:40 +0100
|
||||
Subject: [PATCH 55/93] drm/meson: Convert existing documentation to actual
|
||||
kerneldoc
|
||||
|
||||
---
|
||||
drivers/gpu/drm/meson/meson_canvas.c | 4 +++-
|
||||
drivers/gpu/drm/meson/meson_drv.c | 5 +++--
|
||||
drivers/gpu/drm/meson/meson_dw_hdmi.c | 25 +++++++++++++++++--------
|
||||
drivers/gpu/drm/meson/meson_vclk.c | 22 +++++++++++++++-------
|
||||
drivers/gpu/drm/meson/meson_venc.c | 25 ++++++++++++++++---------
|
||||
drivers/gpu/drm/meson/meson_viu.c | 6 +++++-
|
||||
drivers/gpu/drm/meson/meson_vpp.c | 8 ++++++--
|
||||
7 files changed, 65 insertions(+), 30 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/meson/meson_canvas.c b/drivers/gpu/drm/meson/meson_canvas.c
|
||||
index 4109e36..08f6073 100644
|
||||
--- a/drivers/gpu/drm/meson/meson_canvas.c
|
||||
+++ b/drivers/gpu/drm/meson/meson_canvas.c
|
||||
@@ -24,7 +24,9 @@
|
||||
#include "meson_canvas.h"
|
||||
#include "meson_registers.h"
|
||||
|
||||
-/*
|
||||
+/**
|
||||
+ * DOC: Canvas
|
||||
+ *
|
||||
* CANVAS is a memory zone where physical memory frames information
|
||||
* are stored for the VIU to scanout.
|
||||
*/
|
||||
diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
|
||||
index 4b506d0..4c3422e 100644
|
||||
--- a/drivers/gpu/drm/meson/meson_drv.c
|
||||
+++ b/drivers/gpu/drm/meson/meson_drv.c
|
||||
@@ -52,13 +52,14 @@
|
||||
#define DRIVER_NAME "meson"
|
||||
#define DRIVER_DESC "Amlogic Meson DRM driver"
|
||||
|
||||
-/*
|
||||
- * Video Processing Unit
|
||||
+/**
|
||||
+ * DOC: Video Processing Unit
|
||||
*
|
||||
* VPU Handles the Global Video Processing, it includes management of the
|
||||
* clocks gates, blocks reset lines and power domains.
|
||||
*
|
||||
* What is missing :
|
||||
+ *
|
||||
* - Full reset of entire video processing HW blocks
|
||||
* - Scaling and setup of the VPU clock
|
||||
* - Bus clock gates
|
||||
diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c
|
||||
index 8851dcb..7b86eb7 100644
|
||||
--- a/drivers/gpu/drm/meson/meson_dw_hdmi.c
|
||||
+++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c
|
||||
@@ -42,18 +42,25 @@
|
||||
#define DRIVER_NAME "meson-dw-hdmi"
|
||||
#define DRIVER_DESC "Amlogic Meson HDMI-TX DRM driver"
|
||||
|
||||
-/*
|
||||
+/**
|
||||
+ * DOC: HDMI Output
|
||||
+ *
|
||||
* HDMI Output is composed of :
|
||||
+ *
|
||||
* - A Synopsys DesignWare HDMI Controller IP
|
||||
* - A TOP control block controlling the Clocks and PHY
|
||||
* - A custom HDMI PHY in order convert video to TMDS signal
|
||||
- * ___________________________________
|
||||
- * | HDMI TOP |<= HPD
|
||||
- * |___________________________________|
|
||||
- * | | |
|
||||
- * | Synopsys HDMI | HDMI PHY |=> TMDS
|
||||
- * | Controller |________________|
|
||||
- * |___________________________________|<=> DDC
|
||||
+ *
|
||||
+ * .. code::
|
||||
+ *
|
||||
+ * ___________________________________
|
||||
+ * | HDMI TOP |<= HPD
|
||||
+ * |___________________________________|
|
||||
+ * | | |
|
||||
+ * | Synopsys HDMI | HDMI PHY |=> TMDS
|
||||
+ * | Controller |________________|
|
||||
+ * |___________________________________|<=> DDC
|
||||
+ *
|
||||
*
|
||||
* The HDMI TOP block only supports HPD sensing.
|
||||
* The Synopsys HDMI Controller interrupt is routed
|
||||
@@ -78,6 +85,7 @@
|
||||
* audio source interfaces.
|
||||
*
|
||||
* We handle the following features :
|
||||
+ *
|
||||
* - HPD Rise & Fall interrupt
|
||||
* - HDMI Controller Interrupt
|
||||
* - HDMI PHY Init for 480i to 1080p60
|
||||
@@ -85,6 +93,7 @@
|
||||
* - VENC Mode setup for 480i to 1080p60
|
||||
*
|
||||
* What is missing :
|
||||
+ *
|
||||
* - PHY, Clock and Mode setup for 2k && 4k modes
|
||||
* - SDDC Scrambling mode for HDMI 2.0a
|
||||
* - HDCP Setup
|
||||
diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c
|
||||
index 3731479..4767704 100644
|
||||
--- a/drivers/gpu/drm/meson/meson_vclk.c
|
||||
+++ b/drivers/gpu/drm/meson/meson_vclk.c
|
||||
@@ -23,21 +23,29 @@
|
||||
#include "meson_drv.h"
|
||||
#include "meson_vclk.h"
|
||||
|
||||
-/*
|
||||
+/**
|
||||
+ * DOC: Video Clocks
|
||||
+ *
|
||||
* VCLK is the "Pixel Clock" frequency generator from a dedicated PLL.
|
||||
* We handle the following encodings :
|
||||
+ *
|
||||
* - CVBS 27MHz generator via the VCLK2 to the VENCI and VDAC blocks
|
||||
* - HDMI Pixel Clocks generation
|
||||
+ *
|
||||
* What is missing :
|
||||
+ *
|
||||
* - Genenate Pixel clocks for 2K/4K 10bit formats
|
||||
*
|
||||
* Clock generator scheme :
|
||||
- * __________ _________ _____
|
||||
- * | | | | | |--ENCI
|
||||
- * | HDMI PLL |-| PLL_DIV |--- VCLK--| |--ENCL
|
||||
- * |__________| |_________| \ | MUX |--ENCP
|
||||
- * --VCLK2-| |--VDAC
|
||||
- * |_____|--HDMI-TX
|
||||
+ *
|
||||
+ * .. code::
|
||||
+ *
|
||||
+ * __________ _________ _____
|
||||
+ * | | | | | |--ENCI
|
||||
+ * | HDMI PLL |-| PLL_DIV |--- VCLK--| |--ENCL
|
||||
+ * |__________| |_________| \ | MUX |--ENCP
|
||||
+ * --VCLK2-| |--VDAC
|
||||
+ * |_____|--HDMI-TX
|
||||
*
|
||||
* Final clocks can take input for either VCLK or VCLK2, but
|
||||
* VCLK is the preferred path for HDMI clocking and VCLK2 is the
|
||||
diff --git a/drivers/gpu/drm/meson/meson_venc.c b/drivers/gpu/drm/meson/meson_venc.c
|
||||
index 31dc275..9509017 100644
|
||||
--- a/drivers/gpu/drm/meson/meson_venc.c
|
||||
+++ b/drivers/gpu/drm/meson/meson_venc.c
|
||||
@@ -26,26 +26,33 @@
|
||||
#include "meson_vclk.h"
|
||||
#include "meson_registers.h"
|
||||
|
||||
-/*
|
||||
+/**
|
||||
+ * DOC: Video Encoder
|
||||
+ *
|
||||
* VENC Handle the pixels encoding to the output formats.
|
||||
* We handle the following encodings :
|
||||
+ *
|
||||
* - CVBS Encoding via the ENCI encoder and VDAC digital to analog converter
|
||||
* - TMDS/HDMI Encoding via ENCI_DIV and ENCP
|
||||
* - Setup of more clock rates for HDMI modes
|
||||
*
|
||||
* What is missing :
|
||||
+ *
|
||||
* - LCD Panel encoding via ENCL
|
||||
* - TV Panel encoding via ENCT
|
||||
*
|
||||
* VENC paths :
|
||||
- * _____ _____ ____________________
|
||||
- * vd1---| |-| | | VENC /---------|----VDAC
|
||||
- * vd2---| VIU |-| VPP |-|-----ENCI/-ENCI_DVI-|\
|
||||
- * osd1--| |-| | | \ | X--HDMI-TX
|
||||
- * osd2--|_____|-|_____| | |\-ENCP--ENCP_DVI-|/
|
||||
- * | | |
|
||||
- * | \--ENCL-----------|----LVDS
|
||||
- * |____________________|
|
||||
+ *
|
||||
+ * .. code::
|
||||
+ *
|
||||
+ * _____ _____ ____________________
|
||||
+ * vd1---| |-| | | VENC /---------|----VDAC
|
||||
+ * vd2---| VIU |-| VPP |-|-----ENCI/-ENCI_DVI-|-|
|
||||
+ * osd1--| |-| | | \ | X--HDMI-TX
|
||||
+ * osd2--|_____|-|_____| | |\-ENCP--ENCP_DVI-|-|
|
||||
+ * | | |
|
||||
+ * | \--ENCL-----------|----LVDS
|
||||
+ * |____________________|
|
||||
*
|
||||
* The ENCI is designed for PAl or NTSC encoding and can go through the VDAC
|
||||
* directly for CVBS encoding or through the ENCI_DVI encoder for HDMI.
|
||||
diff --git a/drivers/gpu/drm/meson/meson_viu.c b/drivers/gpu/drm/meson/meson_viu.c
|
||||
index a6de8ba..6bcfa52 100644
|
||||
--- a/drivers/gpu/drm/meson/meson_viu.c
|
||||
+++ b/drivers/gpu/drm/meson/meson_viu.c
|
||||
@@ -28,9 +28,12 @@
|
||||
#include "meson_canvas.h"
|
||||
#include "meson_registers.h"
|
||||
|
||||
-/*
|
||||
+/**
|
||||
+ * DOC: Video Input Unit
|
||||
+ *
|
||||
* VIU Handles the Pixel scanout and the basic Colorspace conversions
|
||||
* We handle the following features :
|
||||
+ *
|
||||
* - OSD1 RGB565/RGB888/xRGB8888 scanout
|
||||
* - RGB conversion to x/cb/cr
|
||||
* - Progressive or Interlace buffer scanout
|
||||
@@ -38,6 +41,7 @@
|
||||
* - HDR OSD matrix for GXL/GXM
|
||||
*
|
||||
* What is missing :
|
||||
+ *
|
||||
* - BGR888/xBGR8888/BGRx8888/BGRx8888 modes
|
||||
* - YUV4:2:2 Y0CbY1Cr scanout
|
||||
* - Conversion to YUV 4:4:4 from 4:2:2 input
|
||||
diff --git a/drivers/gpu/drm/meson/meson_vpp.c b/drivers/gpu/drm/meson/meson_vpp.c
|
||||
index 671909d..27356f8 100644
|
||||
--- a/drivers/gpu/drm/meson/meson_vpp.c
|
||||
+++ b/drivers/gpu/drm/meson/meson_vpp.c
|
||||
@@ -25,16 +25,20 @@
|
||||
#include "meson_vpp.h"
|
||||
#include "meson_registers.h"
|
||||
|
||||
-/*
|
||||
+/**
|
||||
+ * DOC: Video Post Processing
|
||||
+ *
|
||||
* VPP Handles all the Post Processing after the Scanout from the VIU
|
||||
* We handle the following post processings :
|
||||
- * - Postblend : Blends the OSD1 only
|
||||
+ *
|
||||
+ * - Postblend, Blends the OSD1 only
|
||||
* We exclude OSD2, VS1, VS1 and Preblend output
|
||||
* - Vertical OSD Scaler for OSD1 only, we disable vertical scaler and
|
||||
* use it only for interlace scanout
|
||||
* - Intermediate FIFO with default Amlogic values
|
||||
*
|
||||
* What is missing :
|
||||
+ *
|
||||
* - Preblend for video overlay pre-scaling
|
||||
* - OSD2 support for cursor framebuffer
|
||||
* - Video pre-scaling before postblend
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
From e67e63eb718b887790d05491ee42da0bff571460 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Mon, 6 Mar 2017 12:06:35 +0100
|
||||
Subject: [PATCH 56/93] media: uapi: Add RGB and YUV bus formats for Synopsys
|
||||
HDMI TX Controller
|
||||
|
||||
In order to describe the RGB and YUV bus formats used to feed the
|
||||
Synopsys DesignWare HDMI TX Controller, add missing formats to the
|
||||
list of Bus Formats.
|
||||
|
||||
Documentation for these formats is added in a separate patch.
|
||||
|
||||
Reviewed-by: Archit Taneja <architt@codeaurora.org>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
include/uapi/linux/media-bus-format.h | 13 +++++++++++--
|
||||
1 file changed, 11 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/include/uapi/linux/media-bus-format.h b/include/uapi/linux/media-bus-format.h
|
||||
index 2168759..6c8f31c 100644
|
||||
--- a/include/uapi/linux/media-bus-format.h
|
||||
+++ b/include/uapi/linux/media-bus-format.h
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
#define MEDIA_BUS_FMT_FIXED 0x0001
|
||||
|
||||
-/* RGB - next is 0x1018 */
|
||||
+/* RGB - next is 0x101b */
|
||||
#define MEDIA_BUS_FMT_RGB444_1X12 0x1016
|
||||
#define MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE 0x1001
|
||||
#define MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE 0x1002
|
||||
@@ -57,8 +57,11 @@
|
||||
#define MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA 0x1012
|
||||
#define MEDIA_BUS_FMT_ARGB8888_1X32 0x100d
|
||||
#define MEDIA_BUS_FMT_RGB888_1X32_PADHI 0x100f
|
||||
+#define MEDIA_BUS_FMT_RGB101010_1X30 0x1018
|
||||
+#define MEDIA_BUS_FMT_RGB121212_1X36 0x1019
|
||||
+#define MEDIA_BUS_FMT_RGB161616_1X48 0x101a
|
||||
|
||||
-/* YUV (including grey) - next is 0x2026 */
|
||||
+/* YUV (including grey) - next is 0x202c */
|
||||
#define MEDIA_BUS_FMT_Y8_1X8 0x2001
|
||||
#define MEDIA_BUS_FMT_UV8_1X8 0x2015
|
||||
#define MEDIA_BUS_FMT_UYVY8_1_5X8 0x2002
|
||||
@@ -90,12 +93,18 @@
|
||||
#define MEDIA_BUS_FMT_YVYU10_1X20 0x200e
|
||||
#define MEDIA_BUS_FMT_VUY8_1X24 0x2024
|
||||
#define MEDIA_BUS_FMT_YUV8_1X24 0x2025
|
||||
+#define MEDIA_BUS_FMT_UYYVYY8_1X24 0x2026
|
||||
#define MEDIA_BUS_FMT_UYVY12_1X24 0x2020
|
||||
#define MEDIA_BUS_FMT_VYUY12_1X24 0x2021
|
||||
#define MEDIA_BUS_FMT_YUYV12_1X24 0x2022
|
||||
#define MEDIA_BUS_FMT_YVYU12_1X24 0x2023
|
||||
#define MEDIA_BUS_FMT_YUV10_1X30 0x2016
|
||||
+#define MEDIA_BUS_FMT_UYYVYY10_1X30 0x2027
|
||||
#define MEDIA_BUS_FMT_AYUV8_1X32 0x2017
|
||||
+#define MEDIA_BUS_FMT_UYYVYY12_1X36 0x2028
|
||||
+#define MEDIA_BUS_FMT_YUV12_1X36 0x2029
|
||||
+#define MEDIA_BUS_FMT_YUV16_1X48 0x202a
|
||||
+#define MEDIA_BUS_FMT_UYYVYY16_1X48 0x202b
|
||||
|
||||
/* Bayer - next is 0x3021 */
|
||||
#define MEDIA_BUS_FMT_SBGGR8_1X8 0x3001
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
From d074af897d4547d239f93b55c7baa4cf47a9f535 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Tue, 28 Feb 2017 15:22:54 +0100
|
||||
Subject: [PATCH 57/93] Add HDMI support for Odroid-C2
|
||||
|
||||
---
|
||||
.../arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts | 23 ++++++++++++++++++++++
|
||||
1 file changed, 23 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
|
||||
index 492ac35..ee77c3d 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
|
||||
@@ -135,6 +135,17 @@
|
||||
compatible = "mmc-pwrseq-emmc";
|
||||
reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
+
|
||||
+ hdmi-connector {
|
||||
+ compatible = "hdmi-connector";
|
||||
+ type = "a";
|
||||
+
|
||||
+ port {
|
||||
+ hdmi_connector_in: endpoint {
|
||||
+ remote-endpoint = <&hdmi_tx_tmds_out>;
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
};
|
||||
|
||||
&scpi_clocks {
|
||||
@@ -240,3 +251,15 @@
|
||||
vmmc-supply = <&vcc3v3>;
|
||||
vqmmc-supply = <&vcc1v8>;
|
||||
};
|
||||
+
|
||||
+&hdmi_tx {
|
||||
+ status = "okay";
|
||||
+ pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>;
|
||||
+ pinctrl-names = "default";
|
||||
+};
|
||||
+
|
||||
+&hdmi_tx_tmds_port {
|
||||
+ hdmi_tx_tmds_out: endpoint {
|
||||
+ remote-endpoint = <&hdmi_connector_in>;
|
||||
+ };
|
||||
+};
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
From 81da4e20eecc0e1f4447ebd245047d2683e34f2c Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Mon, 9 Jan 2017 12:29:59 +0100
|
||||
Subject: [PATCH 58/93] pinctrl: meson: Add HDMI HPD/DDC pins functions
|
||||
|
||||
Add pinctrl functions for HDMI HPD pin and DDC pins on Amlogic Meson
|
||||
GXL and GXBB SoCs.
|
||||
---
|
||||
drivers/pinctrl/meson/pinctrl-meson-gxbb.c | 19 +++++++++++++++++++
|
||||
drivers/pinctrl/meson/pinctrl-meson-gxl.c | 19 +++++++++++++++++++
|
||||
2 files changed, 38 insertions(+)
|
||||
|
||||
diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
|
||||
index e0bca4d..7671424 100644
|
||||
--- a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
|
||||
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
|
||||
@@ -232,6 +232,10 @@
|
||||
static const unsigned int pwm_f_x_pins[] = { PIN(GPIOX_7, EE_OFF) };
|
||||
static const unsigned int pwm_f_y_pins[] = { PIN(GPIOY_15, EE_OFF) };
|
||||
|
||||
+static const unsigned int hdmi_hpd_pins[] = { PIN(GPIOH_0, EE_OFF) };
|
||||
+static const unsigned int hdmi_sda_pins[] = { PIN(GPIOH_1, EE_OFF) };
|
||||
+static const unsigned int hdmi_scl_pins[] = { PIN(GPIOH_2, EE_OFF) };
|
||||
+
|
||||
static const struct pinctrl_pin_desc meson_gxbb_aobus_pins[] = {
|
||||
MESON_PIN(GPIOAO_0, 0),
|
||||
MESON_PIN(GPIOAO_1, 0),
|
||||
@@ -439,6 +443,11 @@
|
||||
GROUP(eth_txd2, 6, 3),
|
||||
GROUP(eth_txd3, 6, 2),
|
||||
|
||||
+ /* Bank H */
|
||||
+ GROUP(hdmi_hpd, 1, 26),
|
||||
+ GROUP(hdmi_sda, 1, 25),
|
||||
+ GROUP(hdmi_scl, 1, 24),
|
||||
+
|
||||
/* Bank DV */
|
||||
GROUP(uart_tx_b, 2, 29),
|
||||
GROUP(uart_rx_b, 2, 28),
|
||||
@@ -635,6 +644,14 @@
|
||||
"pwm_f_y",
|
||||
};
|
||||
|
||||
+static const char * const hdmi_hpd_groups[] = {
|
||||
+ "hdmi_hpd",
|
||||
+};
|
||||
+
|
||||
+static const char * const hdmi_i2c_groups[] = {
|
||||
+ "hdmi_sda", "hdmi_scl",
|
||||
+};
|
||||
+
|
||||
static const char * const gpio_aobus_groups[] = {
|
||||
"GPIOAO_0", "GPIOAO_1", "GPIOAO_2", "GPIOAO_3", "GPIOAO_4",
|
||||
"GPIOAO_5", "GPIOAO_6", "GPIOAO_7", "GPIOAO_8", "GPIOAO_9",
|
||||
@@ -698,6 +715,8 @@
|
||||
FUNCTION(pwm_e),
|
||||
FUNCTION(pwm_f_x),
|
||||
FUNCTION(pwm_f_y),
|
||||
+ FUNCTION(hdmi_hpd),
|
||||
+ FUNCTION(hdmi_i2c),
|
||||
};
|
||||
|
||||
static struct meson_pmx_func meson_gxbb_aobus_functions[] = {
|
||||
diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxl.c b/drivers/pinctrl/meson/pinctrl-meson-gxl.c
|
||||
index b69743b..56b9324 100644
|
||||
--- a/drivers/pinctrl/meson/pinctrl-meson-gxl.c
|
||||
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxl.c
|
||||
@@ -197,6 +197,10 @@
|
||||
|
||||
static const unsigned int pwm_e_pins[] = { PIN(GPIOX_16, EE_OFF) };
|
||||
|
||||
+static const unsigned int hdmi_hpd_pins[] = { PIN(GPIOH_0, EE_OFF) };
|
||||
+static const unsigned int hdmi_sda_pins[] = { PIN(GPIOH_1, EE_OFF) };
|
||||
+static const unsigned int hdmi_scl_pins[] = { PIN(GPIOH_2, EE_OFF) };
|
||||
+
|
||||
static const struct pinctrl_pin_desc meson_gxl_aobus_pins[] = {
|
||||
MESON_PIN(GPIOAO_0, 0),
|
||||
MESON_PIN(GPIOAO_1, 0),
|
||||
@@ -362,6 +366,11 @@
|
||||
GROUP(eth_txd2, 4, 11),
|
||||
GROUP(eth_txd3, 4, 10),
|
||||
|
||||
+ /* Bank H */
|
||||
+ GROUP(hdmi_hpd, 6, 31),
|
||||
+ GROUP(hdmi_sda, 6, 30),
|
||||
+ GROUP(hdmi_scl, 6, 29),
|
||||
+
|
||||
/* Bank DV */
|
||||
GROUP(uart_tx_b, 2, 16),
|
||||
GROUP(uart_rx_b, 2, 15),
|
||||
@@ -505,6 +514,14 @@
|
||||
"pwm_e",
|
||||
};
|
||||
|
||||
+static const char * const hdmi_hpd_groups[] = {
|
||||
+ "hdmi_hpd",
|
||||
+};
|
||||
+
|
||||
+static const char * const hdmi_i2c_groups[] = {
|
||||
+ "hdmi_sda", "hdmi_scl",
|
||||
+};
|
||||
+
|
||||
static const char * const gpio_aobus_groups[] = {
|
||||
"GPIOAO_0", "GPIOAO_1", "GPIOAO_2", "GPIOAO_3", "GPIOAO_4",
|
||||
"GPIOAO_5", "GPIOAO_6", "GPIOAO_7", "GPIOAO_8", "GPIOAO_9",
|
||||
@@ -536,6 +553,8 @@
|
||||
FUNCTION(i2c_c),
|
||||
FUNCTION(eth),
|
||||
FUNCTION(pwm_e),
|
||||
+ FUNCTION(hdmi_hpd),
|
||||
+ FUNCTION(hdmi_i2c),
|
||||
};
|
||||
|
||||
static struct meson_pmx_func meson_gxl_aobus_functions[] = {
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
From 408bb76cae9d0dbd03cbee0bc374010b3ddadf83 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Fri, 13 Jan 2017 16:23:34 +0100
|
||||
Subject: [PATCH 59/93] ARM64: dts: meson-gx: Add HDMI HPD/DDC pinctrl nodes
|
||||
|
||||
Add pinctrl nodes for HDMI HPD and DDC pins modes for Amlogic Meson GXL
|
||||
and GXBB SoCs.
|
||||
---
|
||||
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 14 ++++++++++++++
|
||||
arch/arm64/boot/dts/amlogic/meson-gxl.dtsi | 14 ++++++++++++++
|
||||
2 files changed, 28 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
index bbb034d..ccbbdbc 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
@@ -465,6 +465,20 @@
|
||||
function = "pwm_f_y";
|
||||
};
|
||||
};
|
||||
+
|
||||
+ hdmi_hpd_pins: hdmi_hpd {
|
||||
+ mux {
|
||||
+ groups = "hdmi_hpd";
|
||||
+ function = "hdmi_hpd";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ hdmi_i2c_pins: hdmi_i2c {
|
||||
+ mux {
|
||||
+ groups = "hdmi_sda", "hdmi_scl";
|
||||
+ function = "hdmi_i2c";
|
||||
+ };
|
||||
+ };
|
||||
};
|
||||
};
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
|
||||
index 6921624..17dbcf6 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
|
||||
@@ -229,6 +229,20 @@
|
||||
function = "pwm_e";
|
||||
};
|
||||
};
|
||||
+
|
||||
+ hdmi_hpd_pins: hdmi_hpd {
|
||||
+ mux {
|
||||
+ groups = "hdmi_hpd";
|
||||
+ function = "hdmi_hpd";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ hdmi_i2c_pins: hdmi_i2c {
|
||||
+ mux {
|
||||
+ groups = "hdmi_sda", "hdmi_scl";
|
||||
+ function = "hdmi_i2c";
|
||||
+ };
|
||||
+ };
|
||||
};
|
||||
|
||||
eth-phy-mux {
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
From 0a0c298ca6a5ec9cfef16b7d2553adc1afdf5eb7 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Fri, 13 Jan 2017 16:03:43 +0100
|
||||
Subject: [PATCH 60/93] clk: meson-gxbb: Export HDMI clocks
|
||||
|
||||
Export HDMI clock from internal to dt-bindings.
|
||||
---
|
||||
drivers/clk/meson/gxbb.h | 4 ++--
|
||||
include/dt-bindings/clock/gxbb-clkc.h | 2 ++
|
||||
2 files changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h
|
||||
index f79ab57..15705d3 100644
|
||||
--- a/drivers/clk/meson/gxbb.h
|
||||
+++ b/drivers/clk/meson/gxbb.h
|
||||
@@ -231,7 +231,7 @@
|
||||
#define CLKID_AHB_DATA_BUS 60
|
||||
#define CLKID_AHB_CTRL_BUS 61
|
||||
#define CLKID_HDMI_INTR_SYNC 62
|
||||
-#define CLKID_HDMI_PCLK 63
|
||||
+/* CLKID_HDMI_PCLK */
|
||||
/* CLKID_USB1_DDR_BRIDGE */
|
||||
/* CLKID_USB0_DDR_BRIDGE */
|
||||
#define CLKID_MMC_PCLK 66
|
||||
@@ -245,7 +245,7 @@
|
||||
#define CLKID_VCLK2_VENCI1 74
|
||||
#define CLKID_VCLK2_VENCP0 75
|
||||
#define CLKID_VCLK2_VENCP1 76
|
||||
-#define CLKID_GCLK_VENCI_INT0 77
|
||||
+/* CLKID_GCLK_VENCI_INT0 */
|
||||
#define CLKID_GCLK_VENCI_INT 78
|
||||
#define CLKID_DAC_CLK 79
|
||||
#define CLKID_AOCLK_GATE 80
|
||||
diff --git a/include/dt-bindings/clock/gxbb-clkc.h b/include/dt-bindings/clock/gxbb-clkc.h
|
||||
index 7bbc1d0..cfd7558 100644
|
||||
--- a/include/dt-bindings/clock/gxbb-clkc.h
|
||||
+++ b/include/dt-bindings/clock/gxbb-clkc.h
|
||||
@@ -19,8 +19,10 @@
|
||||
#define CLKID_USB0 50
|
||||
#define CLKID_USB1 51
|
||||
#define CLKID_USB 55
|
||||
+#define CLKID_HDMI_PCLK 63
|
||||
#define CLKID_USB1_DDR_BRIDGE 64
|
||||
#define CLKID_USB0_DDR_BRIDGE 65
|
||||
+#define CLKID_GCLK_VENCI_INT0 77
|
||||
#define CLKID_AO_I2C 93
|
||||
#define CLKID_SD_EMMC_A 94
|
||||
#define CLKID_SD_EMMC_B 95
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
From 366f348606cdabe13ccd20c34a6bded2463b925e Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Fri, 13 Jan 2017 16:09:58 +0100
|
||||
Subject: [PATCH 61/93] ARM64: dts: meson-gx: Add shared CMA dma memory pool
|
||||
|
||||
The HDMI modes needs more CMA memory to be reserved at boot-time.
|
||||
|
||||
Conflicts:
|
||||
arch/arm64/boot/dts/amlogic/meson-gx.dtsi
|
||||
---
|
||||
arch/arm64/boot/dts/amlogic/meson-gx.dtsi | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
|
||||
index 0cbe24b..fc03f0e 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
|
||||
@@ -71,6 +71,14 @@
|
||||
reg = <0x0 0x10000000 0x0 0x200000>;
|
||||
no-map;
|
||||
};
|
||||
+
|
||||
+ linux,cma {
|
||||
+ compatible = "shared-dma-pool";
|
||||
+ reusable;
|
||||
+ size = <0x0 0xbc00000>;
|
||||
+ alignment = <0x0 0x400000>;
|
||||
+ linux,cma-default;
|
||||
+ };
|
||||
};
|
||||
|
||||
cpus {
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,330 @@
|
|||
From 19d55f4941ae9c08450cf891c7e1588616a54f17 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Mon, 9 Jan 2017 14:21:34 +0100
|
||||
Subject: [PATCH 62/93] ARM64: dts: meson-gx: Add support for HDMI output
|
||||
|
||||
Add HDMI output and connector nodes.
|
||||
---
|
||||
.../arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi | 39 ++++++++++++++++++++++
|
||||
arch/arm64/boot/dts/amlogic/meson-gx.dtsi | 32 ++++++++++++++++++
|
||||
.../boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts | 23 +++++++++++++
|
||||
arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi | 23 +++++++++++++
|
||||
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 12 +++++++
|
||||
.../boot/dts/amlogic/meson-gxl-nexbox-a95x.dts | 23 +++++++++++++
|
||||
arch/arm64/boot/dts/amlogic/meson-gxl.dtsi | 13 ++++++++
|
||||
.../arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts | 23 +++++++++++++
|
||||
arch/arm64/boot/dts/amlogic/meson-gxm.dtsi | 4 +++
|
||||
9 files changed, 192 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
|
||||
index 7a078be..a84e276 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
|
||||
@@ -98,6 +98,27 @@
|
||||
clocks = <&wifi32k>;
|
||||
clock-names = "ext_clock";
|
||||
};
|
||||
+
|
||||
+ cvbs-connector {
|
||||
+ compatible = "composite-video-connector";
|
||||
+
|
||||
+ port {
|
||||
+ cvbs_connector_in: endpoint {
|
||||
+ remote-endpoint = <&cvbs_vdac_out>;
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ hdmi-connector {
|
||||
+ compatible = "hdmi-connector";
|
||||
+ type = "a";
|
||||
+
|
||||
+ port {
|
||||
+ hdmi_connector_in: endpoint {
|
||||
+ remote-endpoint = <&hdmi_tx_tmds_out>;
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
};
|
||||
|
||||
/* This UART is brought out to the DB9 connector */
|
||||
@@ -188,3 +209,21 @@
|
||||
ðmac {
|
||||
status = "okay";
|
||||
};
|
||||
+
|
||||
+&cvbs_vdac_port {
|
||||
+ cvbs_vdac_out: endpoint {
|
||||
+ remote-endpoint = <&cvbs_connector_in>;
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
+&hdmi_tx {
|
||||
+ status = "okay";
|
||||
+ pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>;
|
||||
+ pinctrl-names = "default";
|
||||
+};
|
||||
+
|
||||
+&hdmi_tx_tmds_port {
|
||||
+ hdmi_tx_tmds_out: endpoint {
|
||||
+ remote-endpoint = <&hdmi_connector_in>;
|
||||
+ };
|
||||
+};
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
|
||||
index fc03f0e..ef0b17c 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
|
||||
@@ -397,6 +397,38 @@
|
||||
cvbs_vdac_port: port@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
+
|
||||
+ /* HDMI-TX output port */
|
||||
+ hdmi_tx_port: port@1 {
|
||||
+ reg = <1>;
|
||||
+
|
||||
+ hdmi_tx_out: endpoint {
|
||||
+ remote-endpoint = <&hdmi_tx_in>;
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ hdmi_tx: hdmi-tx@c883a000 {
|
||||
+ compatible = "amlogic,meson-gx-dw-hdmi";
|
||||
+ reg = <0x0 0xc883a000 0x0 0x1c>;
|
||||
+ interrupts = <GIC_SPI 57 IRQ_TYPE_EDGE_RISING>;
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
+ status = "disabled";
|
||||
+
|
||||
+ /* VPU VENC Input */
|
||||
+ hdmi_tx_venc_port: port@0 {
|
||||
+ reg = <0>;
|
||||
+
|
||||
+ hdmi_tx_in: endpoint {
|
||||
+ remote-endpoint = <&hdmi_tx_out>;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ /* TMDS Output */
|
||||
+ hdmi_tx_tmds_port: port@1 {
|
||||
+ reg = <1>;
|
||||
+ };
|
||||
};
|
||||
};
|
||||
};
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts
|
||||
index 4cbd626..a2c999f 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts
|
||||
@@ -152,6 +152,17 @@
|
||||
};
|
||||
};
|
||||
};
|
||||
+
|
||||
+ hdmi-connector {
|
||||
+ compatible = "hdmi-connector";
|
||||
+ type = "a";
|
||||
+
|
||||
+ port {
|
||||
+ hdmi_connector_in: endpoint {
|
||||
+ remote-endpoint = <&hdmi_tx_tmds_out>;
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
};
|
||||
|
||||
&uart_AO {
|
||||
@@ -245,3 +256,15 @@
|
||||
remote-endpoint = <&cvbs_connector_in>;
|
||||
};
|
||||
};
|
||||
+
|
||||
+&hdmi_tx {
|
||||
+ status = "okay";
|
||||
+ pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>;
|
||||
+ pinctrl-names = "default";
|
||||
+};
|
||||
+
|
||||
+&hdmi_tx_tmds_port {
|
||||
+ hdmi_tx_tmds_out: endpoint {
|
||||
+ remote-endpoint = <&hdmi_connector_in>;
|
||||
+ };
|
||||
+};
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
|
||||
index 4a96e0f..1c96fc8 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
|
||||
@@ -135,6 +135,17 @@
|
||||
};
|
||||
};
|
||||
};
|
||||
+
|
||||
+ hdmi-connector {
|
||||
+ compatible = "hdmi-connector";
|
||||
+ type = "a";
|
||||
+
|
||||
+ port {
|
||||
+ hdmi_connector_in: endpoint {
|
||||
+ remote-endpoint = <&hdmi_tx_tmds_out>;
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
};
|
||||
|
||||
/* This UART is brought out to the DB9 connector */
|
||||
@@ -250,3 +261,15 @@
|
||||
remote-endpoint = <&cvbs_connector_in>;
|
||||
};
|
||||
};
|
||||
+
|
||||
+&hdmi_tx {
|
||||
+ status = "okay";
|
||||
+ pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>;
|
||||
+ pinctrl-names = "default";
|
||||
+};
|
||||
+
|
||||
+&hdmi_tx_tmds_port {
|
||||
+ hdmi_tx_tmds_out: endpoint {
|
||||
+ remote-endpoint = <&hdmi_connector_in>;
|
||||
+ };
|
||||
+};
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
index ccbbdbc..b897ad6 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
@@ -563,3 +563,15 @@
|
||||
&vpu {
|
||||
compatible = "amlogic,meson-gxbb-vpu", "amlogic,meson-gx-vpu";
|
||||
};
|
||||
+
|
||||
+&hdmi_tx {
|
||||
+ compatible = "amlogic,meson-gxbb-dw-hdmi", "amlogic,meson-gx-dw-hdmi";
|
||||
+ resets = <&reset RESET_HDMITX_CAPB3>,
|
||||
+ <&reset RESET_HDMI_SYSTEM_RESET>,
|
||||
+ <&reset RESET_HDMI_TX>;
|
||||
+ reset-names = "hdmitx_apb", "hdmitx", "hdmitx_phy";
|
||||
+ clocks = <&clkc CLKID_HDMI_PCLK>,
|
||||
+ <&clkc CLKID_CLK81>,
|
||||
+ <&clkc CLKID_GCLK_VENCI_INT0>;
|
||||
+ clock-names = "isfr", "iahb", "venci";
|
||||
+};
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-nexbox-a95x.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-nexbox-a95x.dts
|
||||
index cea4a3e..8873c05 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxl-nexbox-a95x.dts
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl-nexbox-a95x.dts
|
||||
@@ -127,6 +127,17 @@
|
||||
};
|
||||
};
|
||||
};
|
||||
+
|
||||
+ hdmi-connector {
|
||||
+ compatible = "hdmi-connector";
|
||||
+ type = "a";
|
||||
+
|
||||
+ port {
|
||||
+ hdmi_connector_in: endpoint {
|
||||
+ remote-endpoint = <&hdmi_tx_tmds_out>;
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
};
|
||||
|
||||
&uart_AO {
|
||||
@@ -219,3 +230,15 @@
|
||||
remote-endpoint = <&cvbs_connector_in>;
|
||||
};
|
||||
};
|
||||
+
|
||||
+&hdmi_tx {
|
||||
+ status = "okay";
|
||||
+ pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>;
|
||||
+ pinctrl-names = "default";
|
||||
+};
|
||||
+
|
||||
+&hdmi_tx_tmds_port {
|
||||
+ hdmi_tx_tmds_out: endpoint {
|
||||
+ remote-endpoint = <&hdmi_connector_in>;
|
||||
+ };
|
||||
+};
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
|
||||
index 17dbcf6..bf26974 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
|
||||
@@ -44,6 +44,7 @@
|
||||
#include "meson-gx.dtsi"
|
||||
#include <dt-bindings/clock/gxbb-clkc.h>
|
||||
#include <dt-bindings/gpio/meson-gxl-gpio.h>
|
||||
+#include <dt-bindings/reset/amlogic,meson-gxbb-reset.h>
|
||||
|
||||
/ {
|
||||
compatible = "amlogic,meson-gxl";
|
||||
@@ -317,3 +318,15 @@
|
||||
&vpu {
|
||||
compatible = "amlogic,meson-gxl-vpu", "amlogic,meson-gx-vpu";
|
||||
};
|
||||
+
|
||||
+&hdmi_tx {
|
||||
+ compatible = "amlogic,meson-gxl-dw-hdmi", "amlogic,meson-gx-dw-hdmi";
|
||||
+ resets = <&reset RESET_HDMITX_CAPB3>,
|
||||
+ <&reset RESET_HDMI_SYSTEM_RESET>,
|
||||
+ <&reset RESET_HDMI_TX>;
|
||||
+ reset-names = "hdmitx_apb", "hdmitx", "hdmitx_phy";
|
||||
+ clocks = <&clkc CLKID_HDMI_PCLK>,
|
||||
+ <&clkc CLKID_CLK81>,
|
||||
+ <&clkc CLKID_GCLK_VENCI_INT0>;
|
||||
+ clock-names = "isfr", "iahb", "venci";
|
||||
+};
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts b/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts
|
||||
index 5a337d3..0e68c62e 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts
|
||||
@@ -100,6 +100,17 @@
|
||||
};
|
||||
};
|
||||
};
|
||||
+
|
||||
+ hdmi-connector {
|
||||
+ compatible = "hdmi-connector";
|
||||
+ type = "a";
|
||||
+
|
||||
+ port {
|
||||
+ hdmi_connector_in: endpoint {
|
||||
+ remote-endpoint = <&hdmi_tx_tmds_out>;
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
};
|
||||
|
||||
/* This UART is brought out to the DB9 connector */
|
||||
@@ -183,3 +194,15 @@
|
||||
remote-endpoint = <&cvbs_connector_in>;
|
||||
};
|
||||
};
|
||||
+
|
||||
+&hdmi_tx {
|
||||
+ status = "okay";
|
||||
+ pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>;
|
||||
+ pinctrl-names = "default";
|
||||
+};
|
||||
+
|
||||
+&hdmi_tx_tmds_port {
|
||||
+ hdmi_tx_tmds_out: endpoint {
|
||||
+ remote-endpoint = <&hdmi_connector_in>;
|
||||
+ };
|
||||
+};
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxm.dtsi
|
||||
index eb2f0c3..ac0fc02 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxm.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxm.dtsi
|
||||
@@ -116,3 +116,7 @@
|
||||
&vpu {
|
||||
compatible = "amlogic,meson-gxm-vpu", "amlogic,meson-gx-vpu";
|
||||
};
|
||||
+
|
||||
+&hdmi_tx {
|
||||
+ compatible = "amlogic,meson-gxm-dw-hdmi", "amlogic,meson-gx-dw-hdmi";
|
||||
+};
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
From 411eb0d0f105ae0289753e0243a97410d4be9748 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Tue, 24 Jan 2017 15:12:31 +0100
|
||||
Subject: [PATCH 63/93] clk: gxbb: put dividers and muxes in tables
|
||||
|
||||
Until now, there was only 1 divider and 1 mux declared for the gxbb
|
||||
platform. With the ongoing work on audio this is about to change
|
||||
Use the same approach as gates for dividers and muxes, putting them
|
||||
in tables to fix the register address at runtime.
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
|
||||
Conflicts:
|
||||
drivers/clk/meson/gxbb.c
|
||||
---
|
||||
drivers/clk/meson/gxbb.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
|
||||
index d1dac0f..e17903b 100644
|
||||
--- a/drivers/clk/meson/gxbb.c
|
||||
+++ b/drivers/clk/meson/gxbb.c
|
||||
@@ -954,12 +954,16 @@
|
||||
&gxbb_mali_0_sel,
|
||||
&gxbb_mali_1_sel,
|
||||
&gxbb_mali,
|
||||
+ &gxbb_mpeg_clk_sel,
|
||||
+ &gxbb_sar_adc_clk_sel,
|
||||
};
|
||||
|
||||
static struct clk_divider *gxbb_clk_dividers[] = {
|
||||
&gxbb_mpeg_clk_div,
|
||||
&gxbb_mali_0_div,
|
||||
&gxbb_mali_1_div,
|
||||
+ &gxbb_mpeg_clk_div,
|
||||
+ &gxbb_sar_adc_clk_div,
|
||||
};
|
||||
|
||||
struct gxbb_composite_clk {
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
From e372a783aeeb501b21a5d3d5a0a5d230395d09e1 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Mon, 13 Feb 2017 23:56:13 +0100
|
||||
Subject: [PATCH 64/93] clk: meson: fix SET_PARAM macro
|
||||
|
||||
param val is not enclosed in parathesis which is buggy when given an
|
||||
expression instead of simple value
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
---
|
||||
drivers/clk/meson/clkc.h | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
|
||||
index 22a6335..153b111 100644
|
||||
--- a/drivers/clk/meson/clkc.h
|
||||
+++ b/drivers/clk/meson/clkc.h
|
||||
@@ -25,7 +25,7 @@
|
||||
#define PARM_GET(width, shift, reg) \
|
||||
(((reg) & SETPMASK(width, shift)) >> (shift))
|
||||
#define PARM_SET(width, shift, reg, val) \
|
||||
- (((reg) & CLRPMASK(width, shift)) | (val << (shift)))
|
||||
+ (((reg) & CLRPMASK(width, shift)) | ((val) << (shift)))
|
||||
|
||||
#define MESON_PARM_APPLICABLE(p) (!!((p)->width))
|
||||
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,291 @@
|
|||
From ea9502e463beb9084ba48b6b47f5a95cf6eb50d1 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Wed, 18 Jan 2017 12:17:01 +0100
|
||||
Subject: [PATCH 65/93] clk: meson: mpll: add rw operation
|
||||
|
||||
This patch adds the new callbacks to the meson-mpll driver to control
|
||||
and set the pll rate. For this, we also need to the enable and sdm
|
||||
enable bit, which are added to mpll data structure.
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
---
|
||||
drivers/clk/meson/clk-mpll.c | 152 +++++++++++++++++++++++++++++++++++++++++--
|
||||
drivers/clk/meson/clkc.h | 4 +-
|
||||
drivers/clk/meson/gxbb.c | 30 +++++++++
|
||||
3 files changed, 180 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/drivers/clk/meson/clk-mpll.c b/drivers/clk/meson/clk-mpll.c
|
||||
index 03af790..d4ba8cd 100644
|
||||
--- a/drivers/clk/meson/clk-mpll.c
|
||||
+++ b/drivers/clk/meson/clk-mpll.c
|
||||
@@ -64,16 +64,50 @@
|
||||
#include <linux/clk-provider.h>
|
||||
#include "clkc.h"
|
||||
|
||||
-#define SDM_MAX 16384
|
||||
+#define SDM_DEN 16384
|
||||
+#define SDM_MIN 1
|
||||
+#define SDM_MAX 16383
|
||||
+#define N2_MIN 4
|
||||
+#define N2_MAX 127
|
||||
|
||||
#define to_meson_clk_mpll(_hw) container_of(_hw, struct meson_clk_mpll, hw)
|
||||
|
||||
+static unsigned long rate_from_params(unsigned long parent_rate,
|
||||
+ unsigned long sdm,
|
||||
+ unsigned long n2)
|
||||
+{
|
||||
+ return (parent_rate * SDM_DEN) / ((SDM_DEN * n2) + sdm);
|
||||
+}
|
||||
+
|
||||
+static void params_from_rate(unsigned long requested_rate,
|
||||
+ unsigned long parent_rate,
|
||||
+ unsigned long *sdm,
|
||||
+ unsigned long *n2)
|
||||
+{
|
||||
+ uint64_t div = parent_rate;
|
||||
+ unsigned long rem = do_div(div, requested_rate);
|
||||
+
|
||||
+ if(div < N2_MIN) {
|
||||
+ *n2 = N2_MIN;
|
||||
+ *sdm = SDM_MIN;
|
||||
+ } else if (div > N2_MAX) {
|
||||
+ *n2 = N2_MAX;
|
||||
+ *sdm = SDM_MAX;
|
||||
+ } else {
|
||||
+ *n2 = div;
|
||||
+ *sdm = DIV_ROUND_UP(rem * SDM_DEN, requested_rate);
|
||||
+ if (*sdm < SDM_MIN)
|
||||
+ *sdm = SDM_MIN;
|
||||
+ else if (*sdm > SDM_MAX)
|
||||
+ *sdm = SDM_MAX;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static unsigned long mpll_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
|
||||
struct parm *p;
|
||||
- unsigned long rate = 0;
|
||||
unsigned long reg, sdm, n2;
|
||||
|
||||
p = &mpll->sdm;
|
||||
@@ -84,11 +118,119 @@ static unsigned long mpll_recalc_rate(struct clk_hw *hw,
|
||||
reg = readl(mpll->base + p->reg_off);
|
||||
n2 = PARM_GET(p->width, p->shift, reg);
|
||||
|
||||
- rate = (parent_rate * SDM_MAX) / ((SDM_MAX * n2) + sdm);
|
||||
+ return rate_from_params(parent_rate, sdm, n2);
|
||||
+}
|
||||
+
|
||||
+static long mpll_round_rate(struct clk_hw *hw,
|
||||
+ unsigned long rate,
|
||||
+ unsigned long *parent_rate)
|
||||
+{
|
||||
+ unsigned long sdm, n2;
|
||||
+
|
||||
+ params_from_rate(rate, *parent_rate, &sdm, &n2);
|
||||
+ return rate_from_params(*parent_rate, sdm, n2);
|
||||
+}
|
||||
+
|
||||
+static int mpll_set_rate(struct clk_hw *hw,
|
||||
+ unsigned long rate,
|
||||
+ unsigned long parent_rate)
|
||||
+{
|
||||
+ struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
|
||||
+ struct parm *p;
|
||||
+ unsigned long reg, sdm, n2;
|
||||
+ unsigned long flags = 0;
|
||||
+
|
||||
+ params_from_rate(rate, parent_rate, &sdm, &n2);
|
||||
+
|
||||
+ if (mpll->lock)
|
||||
+ spin_lock_irqsave(mpll->lock, flags);
|
||||
+ else
|
||||
+ __acquire(mpll->lock);
|
||||
+
|
||||
+ p = &mpll->sdm;
|
||||
+ reg = readl(mpll->base + p->reg_off);
|
||||
+ reg = PARM_SET(p->width, p->shift, reg, sdm);
|
||||
+ writel(reg, mpll->base + p->reg_off);
|
||||
+
|
||||
+ p = &mpll->sdm_en;
|
||||
+ reg = readl(mpll->base + p->reg_off);
|
||||
+ reg = PARM_SET(p->width, p->shift, reg, 1);
|
||||
+ writel(reg, mpll->base + p->reg_off);
|
||||
+
|
||||
+ p = &mpll->n2;
|
||||
+ reg = readl(mpll->base + p->reg_off);
|
||||
+ reg = PARM_SET(p->width, p->shift, reg, n2);
|
||||
+ writel(reg, mpll->base + p->reg_off);
|
||||
+
|
||||
+ if (mpll->lock)
|
||||
+ spin_unlock_irqrestore(mpll->lock, flags);
|
||||
+ else
|
||||
+ __release(mpll->lock);
|
||||
|
||||
- return rate;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void mpll_enable_core(struct clk_hw *hw, int enable)
|
||||
+{
|
||||
+ struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
|
||||
+ struct parm *p;
|
||||
+ unsigned long reg;
|
||||
+ unsigned long flags = 0;
|
||||
+
|
||||
+ if (mpll->lock)
|
||||
+ spin_lock_irqsave(mpll->lock, flags);
|
||||
+ else
|
||||
+ __acquire(mpll->lock);
|
||||
+
|
||||
+ p = &mpll->en;
|
||||
+ reg = readl(mpll->base + p->reg_off);
|
||||
+ reg = PARM_SET(p->width, p->shift, reg, enable ? 1 : 0);
|
||||
+ writel(reg, mpll->base + p->reg_off);
|
||||
+
|
||||
+ if (mpll->lock)
|
||||
+ spin_unlock_irqrestore(mpll->lock, flags);
|
||||
+ else
|
||||
+ __release(mpll->lock);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int mpll_enable(struct clk_hw *hw)
|
||||
+{
|
||||
+ mpll_enable_core(hw, 1);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void mpll_disable(struct clk_hw *hw)
|
||||
+{
|
||||
+ mpll_enable_core(hw, 0);
|
||||
+}
|
||||
+
|
||||
+static int mpll_is_enabled(struct clk_hw *hw)
|
||||
+{
|
||||
+ struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
|
||||
+ struct parm *p;
|
||||
+ unsigned long reg;
|
||||
+ int en;
|
||||
+
|
||||
+ p = &mpll->en;
|
||||
+ reg = readl(mpll->base + p->reg_off);
|
||||
+ en = PARM_GET(p->width, p->shift, reg);
|
||||
+
|
||||
+ return en;
|
||||
}
|
||||
|
||||
const struct clk_ops meson_clk_mpll_ro_ops = {
|
||||
- .recalc_rate = mpll_recalc_rate,
|
||||
+ .recalc_rate = mpll_recalc_rate,
|
||||
+ .round_rate = mpll_round_rate,
|
||||
+ .is_enabled = mpll_is_enabled,
|
||||
+};
|
||||
+
|
||||
+const struct clk_ops meson_clk_mpll_ops = {
|
||||
+ .recalc_rate = mpll_recalc_rate,
|
||||
+ .round_rate = mpll_round_rate,
|
||||
+ .set_rate = mpll_set_rate,
|
||||
+ .enable = mpll_enable,
|
||||
+ .disable = mpll_disable,
|
||||
+ .is_enabled = mpll_is_enabled,
|
||||
};
|
||||
diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
|
||||
index 153b111..ae38d69 100644
|
||||
--- a/drivers/clk/meson/clkc.h
|
||||
+++ b/drivers/clk/meson/clkc.h
|
||||
@@ -95,8 +95,9 @@ struct meson_clk_mpll {
|
||||
struct clk_hw hw;
|
||||
void __iomem *base;
|
||||
struct parm sdm;
|
||||
+ struct parm sdm_en;
|
||||
struct parm n2;
|
||||
- /* FIXME ssen gate control? */
|
||||
+ struct parm en;
|
||||
spinlock_t *lock;
|
||||
};
|
||||
|
||||
@@ -119,5 +120,6 @@ struct clk_gate _name = { \
|
||||
extern const struct clk_ops meson_clk_pll_ops;
|
||||
extern const struct clk_ops meson_clk_cpu_ops;
|
||||
extern const struct clk_ops meson_clk_mpll_ro_ops;
|
||||
+extern const struct clk_ops meson_clk_mpll_ops;
|
||||
|
||||
#endif /* __CLKC_H */
|
||||
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
|
||||
index e17903b..2f50a57 100644
|
||||
--- a/drivers/clk/meson/gxbb.c
|
||||
+++ b/drivers/clk/meson/gxbb.c
|
||||
@@ -458,11 +458,21 @@
|
||||
.shift = 0,
|
||||
.width = 14,
|
||||
},
|
||||
+ .sdm_en = {
|
||||
+ .reg_off = HHI_MPLL_CNTL7,
|
||||
+ .shift = 15,
|
||||
+ .width = 1,
|
||||
+ },
|
||||
.n2 = {
|
||||
.reg_off = HHI_MPLL_CNTL7,
|
||||
.shift = 16,
|
||||
.width = 9,
|
||||
},
|
||||
+ .en = {
|
||||
+ .reg_off = HHI_MPLL_CNTL7,
|
||||
+ .shift = 14,
|
||||
+ .width = 1,
|
||||
+ },
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "mpll0",
|
||||
@@ -478,11 +488,21 @@
|
||||
.shift = 0,
|
||||
.width = 14,
|
||||
},
|
||||
+ .sdm_en = {
|
||||
+ .reg_off = HHI_MPLL_CNTL8,
|
||||
+ .shift = 15,
|
||||
+ .width = 1,
|
||||
+ },
|
||||
.n2 = {
|
||||
.reg_off = HHI_MPLL_CNTL8,
|
||||
.shift = 16,
|
||||
.width = 9,
|
||||
},
|
||||
+ .en = {
|
||||
+ .reg_off = HHI_MPLL_CNTL8,
|
||||
+ .shift = 14,
|
||||
+ .width = 1,
|
||||
+ },
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "mpll1",
|
||||
@@ -498,11 +518,21 @@
|
||||
.shift = 0,
|
||||
.width = 14,
|
||||
},
|
||||
+ .sdm_en = {
|
||||
+ .reg_off = HHI_MPLL_CNTL9,
|
||||
+ .shift = 15,
|
||||
+ .width = 1,
|
||||
+ },
|
||||
.n2 = {
|
||||
.reg_off = HHI_MPLL_CNTL9,
|
||||
.shift = 16,
|
||||
.width = 9,
|
||||
},
|
||||
+ .en = {
|
||||
+ .reg_off = HHI_MPLL_CNTL9,
|
||||
+ .shift = 14,
|
||||
+ .width = 1,
|
||||
+ },
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "mpll2",
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
From e3d1a6396f339506d2dd84a276dc8df37da5dcd5 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Wed, 18 Jan 2017 12:19:22 +0100
|
||||
Subject: [PATCH 66/93] clk: meson: gxbb: mpll: use rw operation
|
||||
|
||||
Use read/write operation for the mpll clocks instead of the
|
||||
read-only ones.
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
---
|
||||
drivers/clk/meson/gxbb.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
|
||||
index 2f50a57..1f31933 100644
|
||||
--- a/drivers/clk/meson/gxbb.c
|
||||
+++ b/drivers/clk/meson/gxbb.c
|
||||
@@ -476,7 +476,7 @@
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "mpll0",
|
||||
- .ops = &meson_clk_mpll_ro_ops,
|
||||
+ .ops = &meson_clk_mpll_ops,
|
||||
.parent_names = (const char *[]){ "fixed_pll" },
|
||||
.num_parents = 1,
|
||||
},
|
||||
@@ -506,7 +506,7 @@
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "mpll1",
|
||||
- .ops = &meson_clk_mpll_ro_ops,
|
||||
+ .ops = &meson_clk_mpll_ops,
|
||||
.parent_names = (const char *[]){ "fixed_pll" },
|
||||
.num_parents = 1,
|
||||
},
|
||||
@@ -536,7 +536,7 @@
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "mpll2",
|
||||
- .ops = &meson_clk_mpll_ro_ops,
|
||||
+ .ops = &meson_clk_mpll_ops,
|
||||
.parent_names = (const char *[]){ "fixed_pll" },
|
||||
.num_parents = 1,
|
||||
},
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
From 3adc15dbb8f2b91f8b447397fdbd55650d51c3f7 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Tue, 24 Jan 2017 10:50:40 +0100
|
||||
Subject: [PATCH 67/93] clk: gxbb: add mpll0 enable support
|
||||
|
||||
Unlike mpll1 and mpll2, mpll0 has an additional enable / disable bit in
|
||||
HHI_MPLL_CNTL. Model this oddity by adding a gate at the output of the
|
||||
actual pll.
|
||||
|
||||
To make this transparent to the clock consumer, the existing CLKID_MPLL0
|
||||
id is given to the gate. The actual pll is transfered to CLKID_MPLL0_PLL.
|
||||
|
||||
Fixes: 738f66d3211d ("clk: gxbb: add AmLogic GXBB clk controller driver")
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
|
||||
Conflicts:
|
||||
drivers/clk/meson/gxbb.c
|
||||
drivers/clk/meson/gxbb.h
|
||||
---
|
||||
drivers/clk/meson/gxbb.c | 27 ++++++++++++++++++++++++---
|
||||
drivers/clk/meson/gxbb.h | 3 ++-
|
||||
2 files changed, 26 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
|
||||
index 1f31933..4379a62 100644
|
||||
--- a/drivers/clk/meson/gxbb.c
|
||||
+++ b/drivers/clk/meson/gxbb.c
|
||||
@@ -452,7 +452,13 @@
|
||||
},
|
||||
};
|
||||
|
||||
-static struct meson_clk_mpll gxbb_mpll0 = {
|
||||
+/*
|
||||
+ * Unlike mpll1 and mpll2, mpll0 has an additional enable / disable bit. Let's
|
||||
+ * model this using a clock gate. To make this oddity transparent to the clock
|
||||
+ * consumer, let's give the CLKID_MPLL0 id to the gate and let the rate
|
||||
+ * propagate to the pll itself.
|
||||
+ */
|
||||
+static struct meson_clk_mpll gxbb_mpll0_pll = {
|
||||
.sdm = {
|
||||
.reg_off = HHI_MPLL_CNTL7,
|
||||
.shift = 0,
|
||||
@@ -475,13 +481,26 @@
|
||||
},
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
- .name = "mpll0",
|
||||
+ .name = "mpll0_pll",
|
||||
.ops = &meson_clk_mpll_ops,
|
||||
.parent_names = (const char *[]){ "fixed_pll" },
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
+static struct clk_gate gxbb_mpll0 = {
|
||||
+ .reg = (void *)HHI_MPLL_CNTL,
|
||||
+ .bit_idx = 25,
|
||||
+ .lock = &clk_lock,
|
||||
+ .hw.init = &(struct clk_init_data){
|
||||
+ .name = "mpll0",
|
||||
+ .ops = &clk_gate_ops,
|
||||
+ .parent_names = (const char *[]){ "mpll0_pll" },
|
||||
+ .num_parents = 1,
|
||||
+ .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
static struct meson_clk_mpll gxbb_mpll1 = {
|
||||
.sdm = {
|
||||
.reg_off = HHI_MPLL_CNTL8,
|
||||
@@ -870,6 +889,7 @@
|
||||
[CLKID_SD_EMMC_A] = &gxbb_emmc_a.hw,
|
||||
[CLKID_SD_EMMC_B] = &gxbb_emmc_b.hw,
|
||||
[CLKID_SD_EMMC_C] = &gxbb_emmc_c.hw,
|
||||
+ [CLKID_MPLL0_PLL] = &gxbb_mpll0_pll.hw,
|
||||
[CLKID_MALI] = &gxbb_mali.hw,
|
||||
/* This sentinel entry makes sure the table is large enough */
|
||||
[NR_CLKS] = NULL, /* Sentinel */
|
||||
@@ -887,7 +907,7 @@
|
||||
};
|
||||
|
||||
static struct meson_clk_mpll *const gxbb_clk_mplls[] = {
|
||||
- &gxbb_mpll0,
|
||||
+ &gxbb_mpll0_pll,
|
||||
&gxbb_mpll1,
|
||||
&gxbb_mpll2,
|
||||
};
|
||||
@@ -977,6 +997,7 @@
|
||||
&gxbb_emmc_c,
|
||||
&gxbb_mali_0_en,
|
||||
&gxbb_mali_1_en,
|
||||
+ &gxbb_mpll0,
|
||||
};
|
||||
|
||||
static struct clk_mux *gxbb_clk_muxes[] = {
|
||||
diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h
|
||||
index 15705d3..366b766 100644
|
||||
--- a/drivers/clk/meson/gxbb.h
|
||||
+++ b/drivers/clk/meson/gxbb.h
|
||||
@@ -265,11 +265,12 @@
|
||||
/* CLKID_SD_EMMC_A */
|
||||
/* CLKID_SD_EMMC_B */
|
||||
/* CLKID_SD_EMMC_C */
|
||||
+#define CLKID_MPLL0_PLL 97
|
||||
/* CLKID_MALI_0 */
|
||||
/* CLKID_MALI_1 */
|
||||
/* CLKID_MALI */
|
||||
|
||||
-#define NR_CLKS 100
|
||||
+#define NR_CLKS 101
|
||||
|
||||
/* include the CLKIDs that have been made part of the stable DT binding */
|
||||
#include <dt-bindings/clock/gxbb-clkc.h>
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,209 @@
|
|||
From af43b8d8c91eda0e1cb78e758690a4a282656d48 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Mon, 30 Jan 2017 11:34:32 +0100
|
||||
Subject: [PATCH 68/93] clk: meson8b: add mplls clocks
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
---
|
||||
drivers/clk/meson/meson8b.c | 123 ++++++++++++++++++++++++++++++++++++++++++++
|
||||
drivers/clk/meson/meson8b.h | 21 +++++++-
|
||||
2 files changed, 143 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c
|
||||
index 3f1be46..08644fb 100644
|
||||
--- a/drivers/clk/meson/meson8b.c
|
||||
+++ b/drivers/clk/meson/meson8b.c
|
||||
@@ -246,6 +246,115 @@
|
||||
};
|
||||
|
||||
/*
|
||||
+ * Unlike mpll1 and mpll2, mpll0 has an additional enable / disable bit. Let's
|
||||
+ * model this using a clock gate. To make this oddity transparent to the clock
|
||||
+ * consumer, let's give the CLKID_MPLL0 id to the gate and let the rate
|
||||
+ * propagate to the pll itself.
|
||||
+ */
|
||||
+static struct meson_clk_mpll meson8b_mpll0_pll = {
|
||||
+ .sdm = {
|
||||
+ .reg_off = HHI_MPLL_CNTL7,
|
||||
+ .shift = 0,
|
||||
+ .width = 14,
|
||||
+ },
|
||||
+ .sdm_en = {
|
||||
+ .reg_off = HHI_MPLL_CNTL7,
|
||||
+ .shift = 15,
|
||||
+ .width = 1,
|
||||
+ },
|
||||
+ .n2 = {
|
||||
+ .reg_off = HHI_MPLL_CNTL7,
|
||||
+ .shift = 16,
|
||||
+ .width = 9,
|
||||
+ },
|
||||
+ .en = {
|
||||
+ .reg_off = HHI_MPLL_CNTL7,
|
||||
+ .shift = 14,
|
||||
+ .width = 1,
|
||||
+ },
|
||||
+ .lock = &clk_lock,
|
||||
+ .hw.init = &(struct clk_init_data){
|
||||
+ .name = "mpll0_pll",
|
||||
+ .ops = &meson_clk_mpll_ops,
|
||||
+ .parent_names = (const char *[]){ "fixed_pll" },
|
||||
+ .num_parents = 1,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct clk_gate meson8b_mpll0 = {
|
||||
+ .reg = (void *)HHI_MPLL_CNTL,
|
||||
+ .bit_idx = 25,
|
||||
+ .lock = &clk_lock,
|
||||
+ .hw.init = &(struct clk_init_data){
|
||||
+ .name = "mpll0",
|
||||
+ .ops = &clk_gate_ops,
|
||||
+ .parent_names = (const char *[]){ "mpll0_pll" },
|
||||
+ .num_parents = 1,
|
||||
+ .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct meson_clk_mpll meson8b_mpll1 = {
|
||||
+ .sdm = {
|
||||
+ .reg_off = HHI_MPLL_CNTL8,
|
||||
+ .shift = 0,
|
||||
+ .width = 14,
|
||||
+ },
|
||||
+ .sdm_en = {
|
||||
+ .reg_off = HHI_MPLL_CNTL8,
|
||||
+ .shift = 15,
|
||||
+ .width = 1,
|
||||
+ },
|
||||
+ .n2 = {
|
||||
+ .reg_off = HHI_MPLL_CNTL8,
|
||||
+ .shift = 16,
|
||||
+ .width = 9,
|
||||
+ },
|
||||
+ .en = {
|
||||
+ .reg_off = HHI_MPLL_CNTL8,
|
||||
+ .shift = 14,
|
||||
+ .width = 1,
|
||||
+ },
|
||||
+ .lock = &clk_lock,
|
||||
+ .hw.init = &(struct clk_init_data){
|
||||
+ .name = "mpll1",
|
||||
+ .ops = &meson_clk_mpll_ops,
|
||||
+ .parent_names = (const char *[]){ "fixed_pll" },
|
||||
+ .num_parents = 1,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct meson_clk_mpll meson8b_mpll2 = {
|
||||
+ .sdm = {
|
||||
+ .reg_off = HHI_MPLL_CNTL9,
|
||||
+ .shift = 0,
|
||||
+ .width = 14,
|
||||
+ },
|
||||
+ .sdm_en = {
|
||||
+ .reg_off = HHI_MPLL_CNTL9,
|
||||
+ .shift = 15,
|
||||
+ .width = 1,
|
||||
+ },
|
||||
+ .n2 = {
|
||||
+ .reg_off = HHI_MPLL_CNTL9,
|
||||
+ .shift = 16,
|
||||
+ .width = 9,
|
||||
+ },
|
||||
+ .en = {
|
||||
+ .reg_off = HHI_MPLL_CNTL9,
|
||||
+ .shift = 14,
|
||||
+ .width = 1,
|
||||
+ },
|
||||
+ .lock = &clk_lock,
|
||||
+ .hw.init = &(struct clk_init_data){
|
||||
+ .name = "mpll2",
|
||||
+ .ops = &meson_clk_mpll_ops,
|
||||
+ .parent_names = (const char *[]){ "fixed_pll" },
|
||||
+ .num_parents = 1,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
* FIXME cpu clocks and the legacy composite clocks (e.g. clk81) are both PLL
|
||||
* post-dividers and should be modeled with their respective PLLs via the
|
||||
* forthcoming coordinated clock rates feature
|
||||
@@ -491,6 +600,10 @@ struct clk_gate meson8b_clk81 = {
|
||||
[CLKID_AO_AHB_SRAM] = &meson8b_ao_ahb_sram.hw,
|
||||
[CLKID_AO_AHB_BUS] = &meson8b_ao_ahb_bus.hw,
|
||||
[CLKID_AO_IFACE] = &meson8b_ao_iface.hw,
|
||||
+ [CLKID_MPLL0_PLL] = &meson8b_mpll0_pll.hw,
|
||||
+ [CLKID_MPLL0] = &meson8b_mpll0.hw,
|
||||
+ [CLKID_MPLL1] = &meson8b_mpll1.hw,
|
||||
+ [CLKID_MPLL2] = &meson8b_mpll2.hw,
|
||||
},
|
||||
.num = CLK_NR_CLKS,
|
||||
};
|
||||
@@ -501,6 +614,12 @@ struct clk_gate meson8b_clk81 = {
|
||||
&meson8b_sys_pll,
|
||||
};
|
||||
|
||||
+static struct meson_clk_mpll *const meson8b_clk_mplls[] = {
|
||||
+ &meson8b_mpll0_pll,
|
||||
+ &meson8b_mpll1,
|
||||
+ &meson8b_mpll2,
|
||||
+};
|
||||
+
|
||||
static struct clk_gate *meson8b_clk_gates[] = {
|
||||
&meson8b_clk81,
|
||||
&meson8b_ddr,
|
||||
@@ -601,6 +720,10 @@ static int meson8b_clkc_probe(struct platform_device *pdev)
|
||||
for (i = 0; i < ARRAY_SIZE(meson8b_clk_plls); i++)
|
||||
meson8b_clk_plls[i]->base = clk_base;
|
||||
|
||||
+ /* Populate base address for MPLLs */
|
||||
+ for (i = 0; i < ARRAY_SIZE(meson8b_clk_mplls); i++)
|
||||
+ meson8b_clk_mplls[i]->base = clk_base;
|
||||
+
|
||||
/* Populate the base address for CPU clk */
|
||||
meson8b_cpu_clk.base = clk_base;
|
||||
|
||||
diff --git a/drivers/clk/meson/meson8b.h b/drivers/clk/meson/meson8b.h
|
||||
index 010e958..0f1f05b 100644
|
||||
--- a/drivers/clk/meson/meson8b.h
|
||||
+++ b/drivers/clk/meson/meson8b.h
|
||||
@@ -42,6 +42,21 @@
|
||||
#define HHI_VID_PLL_CNTL 0x320 /* 0xc8 offset in data sheet */
|
||||
|
||||
/*
|
||||
+ * MPLL register offeset taken from the S905 datasheet. Vendor kernel source
|
||||
+ * confirm these are the same for the S805.
|
||||
+ */
|
||||
+#define HHI_MPLL_CNTL 0x280 /* 0xa0 offset in data sheet */
|
||||
+#define HHI_MPLL_CNTL2 0x284 /* 0xa1 offset in data sheet */
|
||||
+#define HHI_MPLL_CNTL3 0x288 /* 0xa2 offset in data sheet */
|
||||
+#define HHI_MPLL_CNTL4 0x28C /* 0xa3 offset in data sheet */
|
||||
+#define HHI_MPLL_CNTL5 0x290 /* 0xa4 offset in data sheet */
|
||||
+#define HHI_MPLL_CNTL6 0x294 /* 0xa5 offset in data sheet */
|
||||
+#define HHI_MPLL_CNTL7 0x298 /* MP0, 0xa6 offset in data sheet */
|
||||
+#define HHI_MPLL_CNTL8 0x29C /* MP1, 0xa7 offset in data sheet */
|
||||
+#define HHI_MPLL_CNTL9 0x2A0 /* MP2, 0xa8 offset in data sheet */
|
||||
+#define HHI_MPLL_CNTL10 0x2A4 /* MP2, 0xa9 offset in data sheet */
|
||||
+
|
||||
+/*
|
||||
* CLKID index values
|
||||
*
|
||||
* These indices are entirely contrived and do not map onto the hardware.
|
||||
@@ -142,8 +157,12 @@
|
||||
#define CLKID_AO_AHB_SRAM 90
|
||||
#define CLKID_AO_AHB_BUS 91
|
||||
#define CLKID_AO_IFACE 92
|
||||
+#define CLKID_MPLL0_PLL 93
|
||||
+#define CLKID_MPLL0 94
|
||||
+#define CLKID_MPLL1 95
|
||||
+#define CLKID_MPLL2 96
|
||||
|
||||
-#define CLK_NR_CLKS 93
|
||||
+#define CLK_NR_CLKS 97
|
||||
|
||||
/* include the CLKIDs that have been made part of the stable DT binding */
|
||||
#include <dt-bindings/clock/meson8b-clkc.h>
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
From 0eb5b137e2cc8daeef7bb3a56c42e104510953a7 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Tue, 14 Feb 2017 14:09:48 +0100
|
||||
Subject: [PATCH 69/93] clk: meson: mpll: correct N2 maximum value
|
||||
|
||||
Documentation say N2 maximum value is 127 but the register field
|
||||
is 9 bits wide, the maximum value should 511.
|
||||
|
||||
Test shows value greater than 127 works well
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
---
|
||||
drivers/clk/meson/clk-mpll.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/clk/meson/clk-mpll.c b/drivers/clk/meson/clk-mpll.c
|
||||
index d4ba8cd..ce48f65 100644
|
||||
--- a/drivers/clk/meson/clk-mpll.c
|
||||
+++ b/drivers/clk/meson/clk-mpll.c
|
||||
@@ -68,7 +68,7 @@
|
||||
#define SDM_MIN 1
|
||||
#define SDM_MAX 16383
|
||||
#define N2_MIN 4
|
||||
-#define N2_MAX 127
|
||||
+#define N2_MAX 511
|
||||
|
||||
#define to_meson_clk_mpll(_hw) container_of(_hw, struct meson_clk_mpll, hw)
|
||||
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,257 @@
|
|||
From 293cec787c3f707d468e62a09d3d5a461717a3a8 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Tue, 14 Feb 2017 00:13:55 +0100
|
||||
Subject: [PATCH 70/93] clk: meson: add audio clock divider support
|
||||
|
||||
The audio divider needs a specific clock divider driver.
|
||||
With am mpll parent clock, which is able to provide fairly precise rate,
|
||||
the generic divider tends to select low value of the divider. In such case
|
||||
the quality of the clock is very poor. For the same final rate, maximizing
|
||||
the audio clock divider value and selecting the corresponding mpll rate
|
||||
gives better results. This is what this driver aims to acheive. So far, so
|
||||
good.
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
---
|
||||
drivers/clk/meson/Makefile | 2 +-
|
||||
drivers/clk/meson/clk-audio-divider.c | 188 ++++++++++++++++++++++++++++++++++
|
||||
drivers/clk/meson/clkc.h | 10 ++
|
||||
3 files changed, 199 insertions(+), 1 deletion(-)
|
||||
create mode 100644 drivers/clk/meson/clk-audio-divider.c
|
||||
|
||||
diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
|
||||
index 3495834..83b6d9d 100644
|
||||
--- a/drivers/clk/meson/Makefile
|
||||
+++ b/drivers/clk/meson/Makefile
|
||||
@@ -2,6 +2,6 @@
|
||||
# Makefile for Meson specific clk
|
||||
#
|
||||
|
||||
-obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-cpu.o clk-mpll.o
|
||||
+obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-cpu.o clk-mpll.o clk-audio-divider.o
|
||||
obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o
|
||||
obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o
|
||||
diff --git a/drivers/clk/meson/clk-audio-divider.c b/drivers/clk/meson/clk-audio-divider.c
|
||||
new file mode 100644
|
||||
index 0000000..2263214
|
||||
--- /dev/null
|
||||
+++ b/drivers/clk/meson/clk-audio-divider.c
|
||||
@@ -0,0 +1,188 @@
|
||||
+/*
|
||||
+ * This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
+ * redistributing this file, you may do so under either license.
|
||||
+ *
|
||||
+ * GPL LICENSE SUMMARY
|
||||
+ *
|
||||
+ * Copyright (c) 2017 AmLogic, Inc.
|
||||
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of version 2 of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful, but
|
||||
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ * General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with this program; if not, write to the Free Software
|
||||
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
+ * The full GNU General Public License is included in this distribution
|
||||
+ * in the file called COPYING
|
||||
+ *
|
||||
+ * BSD LICENSE
|
||||
+ *
|
||||
+ * Copyright (c) 2017 AmLogic, Inc.
|
||||
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
|
||||
+ *
|
||||
+ * Redistribution and use in source and binary forms, with or without
|
||||
+ * modification, are permitted provided that the following conditions
|
||||
+ * are met:
|
||||
+ *
|
||||
+ * * Redistributions of source code must retain the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer.
|
||||
+ * * Redistributions in binary form must reproduce the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer in
|
||||
+ * the documentation and/or other materials provided with the
|
||||
+ * distribution.
|
||||
+ * * Neither the name of Baylibre nor the names of its
|
||||
+ * contributors may be used to endorse or promote products derived
|
||||
+ * from this software without specific prior written permission.
|
||||
+ *
|
||||
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
+ */
|
||||
+
|
||||
+/*
|
||||
+ * Audio clock divider: The algorythm of clk-divider used with a very precise
|
||||
+ * source clock such as the mpll tends to select low divider factor. This gives
|
||||
+ * very poor results with this particular divider especially with high
|
||||
+ * frequencies ( > 100 MHz)
|
||||
+ *
|
||||
+ * This driver try to select the maximum possible divider with the rate the mpll
|
||||
+ * can provide.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/clk-provider.h>
|
||||
+#include "clkc.h"
|
||||
+
|
||||
+#define to_meson_clk_audio_divider(_hw) container_of(_hw, \
|
||||
+ struct meson_clk_audio_divider, hw)
|
||||
+
|
||||
+static int _div_round(unsigned long parent_rate, unsigned long rate,
|
||||
+ unsigned long flags)
|
||||
+{
|
||||
+ if (flags & CLK_DIVIDER_ROUND_CLOSEST)
|
||||
+ return DIV_ROUND_CLOSEST_ULL((u64)parent_rate, rate);
|
||||
+
|
||||
+ return DIV_ROUND_UP_ULL((u64)parent_rate, rate);
|
||||
+}
|
||||
+
|
||||
+static int _get_val(unsigned long parent_rate, unsigned long rate)
|
||||
+{
|
||||
+ return DIV_ROUND_UP_ULL((u64)parent_rate, rate) - 1;
|
||||
+}
|
||||
+
|
||||
+static int _valid_divider(struct clk_hw *hw, int divider)
|
||||
+{
|
||||
+ struct meson_clk_audio_divider *adiv =
|
||||
+ to_meson_clk_audio_divider(hw);
|
||||
+ int max_divider;
|
||||
+ u8 width;
|
||||
+
|
||||
+ width = adiv->div.width;
|
||||
+ max_divider = 1 << width;
|
||||
+
|
||||
+ if (divider < 1)
|
||||
+ return 1;
|
||||
+ else if (divider > max_divider)
|
||||
+ return max_divider;
|
||||
+
|
||||
+ return divider;
|
||||
+}
|
||||
+
|
||||
+static unsigned long audio_divider_recalc_rate(struct clk_hw *hw,
|
||||
+ unsigned long parent_rate)
|
||||
+{
|
||||
+ struct meson_clk_audio_divider *adiv =
|
||||
+ to_meson_clk_audio_divider(hw);
|
||||
+ struct parm *p;
|
||||
+ unsigned long reg, divider;
|
||||
+
|
||||
+ p = &adiv->div;
|
||||
+ reg = readl(adiv->base + p->reg_off);
|
||||
+ divider = PARM_GET(p->width, p->shift, reg) + 1;
|
||||
+
|
||||
+ return DIV_ROUND_UP_ULL((u64)parent_rate, divider);
|
||||
+}
|
||||
+
|
||||
+static long audio_divider_round_rate(struct clk_hw *hw,
|
||||
+ unsigned long rate,
|
||||
+ unsigned long *parent_rate)
|
||||
+{
|
||||
+ struct meson_clk_audio_divider *adiv =
|
||||
+ to_meson_clk_audio_divider(hw);
|
||||
+ unsigned long max_prate;
|
||||
+ int divider;
|
||||
+
|
||||
+ if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
|
||||
+ divider = _div_round(*parent_rate, rate, adiv->flags);
|
||||
+ divider = _valid_divider(hw, divider);
|
||||
+ return DIV_ROUND_UP_ULL((u64)*parent_rate, divider);
|
||||
+ }
|
||||
+
|
||||
+ /* Get the maximum parent rate */
|
||||
+ max_prate = clk_hw_round_rate(clk_hw_get_parent(hw), ULONG_MAX);
|
||||
+
|
||||
+ /* Get the corresponding rounded down divider */
|
||||
+ divider = max_prate / rate;
|
||||
+ divider = _valid_divider(hw, divider);
|
||||
+
|
||||
+ /* Get actual rate of the parent */
|
||||
+ *parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
|
||||
+ divider * rate);
|
||||
+
|
||||
+ return DIV_ROUND_UP_ULL((u64)*parent_rate, divider);
|
||||
+}
|
||||
+
|
||||
+static int audio_divider_set_rate(struct clk_hw *hw,
|
||||
+ unsigned long rate,
|
||||
+ unsigned long parent_rate)
|
||||
+{
|
||||
+ struct meson_clk_audio_divider *adiv =
|
||||
+ to_meson_clk_audio_divider(hw);
|
||||
+ struct parm *p;
|
||||
+ unsigned long reg, flags = 0;
|
||||
+ int val;
|
||||
+
|
||||
+ val = _get_val(parent_rate, rate);
|
||||
+
|
||||
+ if (adiv->lock)
|
||||
+ spin_lock_irqsave(adiv->lock, flags);
|
||||
+ else
|
||||
+ __acquire(adiv->lock);
|
||||
+
|
||||
+ p = &adiv->div;
|
||||
+ reg = readl(adiv->base + p->reg_off);
|
||||
+ reg = PARM_SET(p->width, p->shift, reg, val);
|
||||
+ writel(reg, adiv->base + p->reg_off);
|
||||
+
|
||||
+ if (adiv->lock)
|
||||
+ spin_unlock_irqrestore(adiv->lock, flags);
|
||||
+ else
|
||||
+ __release(adiv->lock);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+const struct clk_ops meson_clk_audio_divider_ro_ops = {
|
||||
+ .recalc_rate = audio_divider_recalc_rate,
|
||||
+ .round_rate = audio_divider_round_rate,
|
||||
+};
|
||||
+
|
||||
+const struct clk_ops meson_clk_audio_divider_ops = {
|
||||
+ .recalc_rate = audio_divider_recalc_rate,
|
||||
+ .round_rate = audio_divider_round_rate,
|
||||
+ .set_rate = audio_divider_set_rate,
|
||||
+};
|
||||
diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
|
||||
index ae38d69..3d4a5bc 100644
|
||||
--- a/drivers/clk/meson/clkc.h
|
||||
+++ b/drivers/clk/meson/clkc.h
|
||||
@@ -101,6 +101,14 @@ struct meson_clk_mpll {
|
||||
spinlock_t *lock;
|
||||
};
|
||||
|
||||
+struct meson_clk_audio_divider {
|
||||
+ struct clk_hw hw;
|
||||
+ void __iomem *base;
|
||||
+ struct parm div;
|
||||
+ u8 flags;
|
||||
+ spinlock_t *lock;
|
||||
+};
|
||||
+
|
||||
#define MESON_GATE(_name, _reg, _bit) \
|
||||
struct clk_gate _name = { \
|
||||
.reg = (void __iomem *) _reg, \
|
||||
@@ -121,5 +129,7 @@ struct clk_gate _name = { \
|
||||
extern const struct clk_ops meson_clk_cpu_ops;
|
||||
extern const struct clk_ops meson_clk_mpll_ro_ops;
|
||||
extern const struct clk_ops meson_clk_mpll_ops;
|
||||
+extern const struct clk_ops meson_clk_audio_divider_ro_ops;
|
||||
+extern const struct clk_ops meson_clk_audio_divider_ops;
|
||||
|
||||
#endif /* __CLKC_H */
|
||||
--
|
||||
1.9.1
|
||||
|
132
patch/kernel/odroidc2-next/0071-clk-gxbb-add-cts_amclk.patch
Normal file
132
patch/kernel/odroidc2-next/0071-clk-gxbb-add-cts_amclk.patch
Normal file
|
@ -0,0 +1,132 @@
|
|||
From a47430e7903c2c9f68568b5f33ea4d508718df28 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Tue, 24 Jan 2017 18:35:23 +0100
|
||||
Subject: [PATCH 71/93] clk: gxbb: add cts_amclk
|
||||
|
||||
Add the i2s master clock also referred as cts_amclk
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
|
||||
Conflicts:
|
||||
drivers/clk/meson/gxbb.c
|
||||
drivers/clk/meson/gxbb.h
|
||||
---
|
||||
drivers/clk/meson/gxbb.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
drivers/clk/meson/gxbb.h | 5 ++++-
|
||||
2 files changed, 57 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
|
||||
index 4379a62..9e2e407 100644
|
||||
--- a/drivers/clk/meson/gxbb.c
|
||||
+++ b/drivers/clk/meson/gxbb.c
|
||||
@@ -699,6 +699,51 @@
|
||||
},
|
||||
};
|
||||
|
||||
+static struct clk_mux gxbb_cts_amclk_sel = {
|
||||
+ .reg = (void *) HHI_AUD_CLK_CNTL,
|
||||
+ .mask = 0x3,
|
||||
+ .shift = 9,
|
||||
+ /* Default parent unknown (register reset value: 0) */
|
||||
+ .table = (u32[]){ 1, 2, 3 },
|
||||
+ .lock = &clk_lock,
|
||||
+ .hw.init = &(struct clk_init_data){
|
||||
+ .name = "cts_amclk_sel",
|
||||
+ .ops = &clk_mux_ops,
|
||||
+ .parent_names = (const char *[]){ "mpll0", "mpll1", "mpll2" },
|
||||
+ .num_parents = 2,
|
||||
+ .flags = CLK_SET_RATE_PARENT,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct meson_clk_audio_divider gxbb_cts_amclk_div = {
|
||||
+ .div = {
|
||||
+ .reg_off = HHI_AUD_CLK_CNTL,
|
||||
+ .shift = 0,
|
||||
+ .width = 8,
|
||||
+ },
|
||||
+ .lock = &clk_lock,
|
||||
+ .hw.init = &(struct clk_init_data){
|
||||
+ .name = "cts_amclk_div",
|
||||
+ .ops = &meson_clk_audio_divider_ops,
|
||||
+ .parent_names = (const char *[]){ "cts_amclk_sel" },
|
||||
+ .num_parents = 1,
|
||||
+ .flags = CLK_SET_RATE_PARENT | CLK_DIVIDER_ROUND_CLOSEST,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct clk_gate gxbb_cts_amclk = {
|
||||
+ .reg = (void *) HHI_AUD_CLK_CNTL,
|
||||
+ .bit_idx = 8,
|
||||
+ .lock = &clk_lock,
|
||||
+ .hw.init = &(struct clk_init_data){
|
||||
+ .name = "cts_amclk",
|
||||
+ .ops = &clk_gate_ops,
|
||||
+ .parent_names = (const char *[]){ "cts_amclk_div" },
|
||||
+ .num_parents = 1,
|
||||
+ .flags = CLK_SET_RATE_PARENT,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
/* Everything Else (EE) domain gates */
|
||||
static MESON_GATE(gxbb_ddr, HHI_GCLK_MPEG0, 0);
|
||||
static MESON_GATE(gxbb_dos, HHI_GCLK_MPEG0, 1);
|
||||
@@ -890,6 +935,9 @@
|
||||
[CLKID_SD_EMMC_B] = &gxbb_emmc_b.hw,
|
||||
[CLKID_SD_EMMC_C] = &gxbb_emmc_c.hw,
|
||||
[CLKID_MPLL0_PLL] = &gxbb_mpll0_pll.hw,
|
||||
+ [CLKID_CTS_AMCLK] = &gxbb_cts_amclk.hw,
|
||||
+ [CLKID_CTS_AMCLK_SEL] = &gxbb_cts_amclk_sel.hw,
|
||||
+ [CLKID_CTS_AMCLK_DIV] = &gxbb_cts_amclk_div.hw,
|
||||
[CLKID_MALI] = &gxbb_mali.hw,
|
||||
/* This sentinel entry makes sure the table is large enough */
|
||||
[NR_CLKS] = NULL, /* Sentinel */
|
||||
@@ -998,6 +1046,7 @@
|
||||
&gxbb_mali_0_en,
|
||||
&gxbb_mali_1_en,
|
||||
&gxbb_mpll0,
|
||||
+ &gxbb_cts_amclk,
|
||||
};
|
||||
|
||||
static struct clk_mux *gxbb_clk_muxes[] = {
|
||||
@@ -1007,6 +1056,7 @@
|
||||
&gxbb_mali,
|
||||
&gxbb_mpeg_clk_sel,
|
||||
&gxbb_sar_adc_clk_sel,
|
||||
+ &gxbb_cts_amclk_sel,
|
||||
};
|
||||
|
||||
static struct clk_divider *gxbb_clk_dividers[] = {
|
||||
@@ -1108,6 +1158,9 @@ static int gxbb_clkc_probe(struct platform_device *pdev)
|
||||
gxbb_gp0_init_regs[i] = clk_base +
|
||||
(u64)gxbb_gp0_init_regs[i];
|
||||
|
||||
+ /* Populate base address for the audio divider */
|
||||
+ gxbb_cts_amclk_div.base = clk_base;
|
||||
+
|
||||
/*
|
||||
* register all clks
|
||||
*/
|
||||
diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h
|
||||
index 366b766..298bfa5 100644
|
||||
--- a/drivers/clk/meson/gxbb.h
|
||||
+++ b/drivers/clk/meson/gxbb.h
|
||||
@@ -266,11 +266,14 @@
|
||||
/* CLKID_SD_EMMC_B */
|
||||
/* CLKID_SD_EMMC_C */
|
||||
#define CLKID_MPLL0_PLL 97
|
||||
+#define CLKID_CTS_AMCLK 98
|
||||
+#define CLKID_CTS_AMCLK_SEL 99
|
||||
+#define CLKID_CTS_AMCLK_DIV 100
|
||||
/* CLKID_MALI_0 */
|
||||
/* CLKID_MALI_1 */
|
||||
/* CLKID_MALI */
|
||||
|
||||
-#define NR_CLKS 101
|
||||
+#define NR_CLKS 104
|
||||
|
||||
/* include the CLKIDs that have been made part of the stable DT binding */
|
||||
#include <dt-bindings/clock/gxbb-clkc.h>
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
From b6e925eebfd802b2dd592c634db24f8cf6202461 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Thu, 26 Jan 2017 11:07:13 +0100
|
||||
Subject: [PATCH 72/93] pinctrl: meson: add i2s output pins
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
---
|
||||
drivers/pinctrl/meson/pinctrl-meson-gxbb.c | 31 ++++++++++++++++++++++++++++++
|
||||
1 file changed, 31 insertions(+)
|
||||
|
||||
diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
|
||||
index 7671424..1ed61d7 100644
|
||||
--- a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
|
||||
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
|
||||
@@ -236,6 +236,10 @@
|
||||
static const unsigned int hdmi_sda_pins[] = { PIN(GPIOH_1, EE_OFF) };
|
||||
static const unsigned int hdmi_scl_pins[] = { PIN(GPIOH_2, EE_OFF) };
|
||||
|
||||
+static const unsigned int i2s_out_ch23_y_pins[] = { PIN(GPIOY_8, EE_OFF) };
|
||||
+static const unsigned int i2s_out_ch45_y_pins[] = { PIN(GPIOY_9, EE_OFF) };
|
||||
+static const unsigned int i2s_out_ch67_y_pins[] = { PIN(GPIOY_10, EE_OFF) };
|
||||
+
|
||||
static const struct pinctrl_pin_desc meson_gxbb_aobus_pins[] = {
|
||||
MESON_PIN(GPIOAO_0, 0),
|
||||
MESON_PIN(GPIOAO_1, 0),
|
||||
@@ -274,6 +278,13 @@
|
||||
static const unsigned int pwm_ao_a_12_pins[] = { PIN(GPIOAO_12, 0) };
|
||||
static const unsigned int pwm_ao_b_pins[] = { PIN(GPIOAO_13, 0) };
|
||||
|
||||
+static const unsigned int i2s_am_clk_pins[] = { PIN(GPIOAO_8, 0) };
|
||||
+static const unsigned int i2s_out_ao_clk_pins[] = { PIN(GPIOAO_9, 0) };
|
||||
+static const unsigned int i2s_out_lr_clk_pins[] = { PIN(GPIOAO_10, 0) };
|
||||
+static const unsigned int i2s_out_ch01_ao_pins[] = { PIN(GPIOAO_11, 0) };
|
||||
+static const unsigned int i2s_out_ch23_ao_pins[] = { PIN(GPIOAO_12, 0) };
|
||||
+static const unsigned int i2s_out_ch45_ao_pins[] = { PIN(GPIOAO_13, 0) };
|
||||
+
|
||||
static struct meson_pmx_group meson_gxbb_periphs_groups[] = {
|
||||
GPIO_GROUP(GPIOZ_0, EE_OFF),
|
||||
GPIO_GROUP(GPIOZ_1, EE_OFF),
|
||||
@@ -426,6 +437,9 @@
|
||||
GROUP(uart_rx_c, 1, 16),
|
||||
GROUP(pwm_a_y, 1, 21),
|
||||
GROUP(pwm_f_y, 1, 20),
|
||||
+ GROUP(i2s_out_ch23_y, 1, 5),
|
||||
+ GROUP(i2s_out_ch45_y, 1, 6),
|
||||
+ GROUP(i2s_out_ch67_y, 1, 7),
|
||||
|
||||
/* Bank Z */
|
||||
GROUP(eth_mdio, 6, 1),
|
||||
@@ -523,6 +537,12 @@
|
||||
GROUP(pwm_ao_a_6, 0, 18),
|
||||
GROUP(pwm_ao_a_12, 0, 17),
|
||||
GROUP(pwm_ao_b, 0, 3),
|
||||
+ GROUP(i2s_am_clk, 0, 30),
|
||||
+ GROUP(i2s_out_ao_clk, 0, 29),
|
||||
+ GROUP(i2s_out_lr_clk, 0, 28),
|
||||
+ GROUP(i2s_out_ch01_ao, 0, 27),
|
||||
+ GROUP(i2s_out_ch23_ao, 1, 0),
|
||||
+ GROUP(i2s_out_ch45_ao, 1, 1),
|
||||
};
|
||||
|
||||
static const char * const gpio_periphs_groups[] = {
|
||||
@@ -652,6 +672,10 @@
|
||||
"hdmi_sda", "hdmi_scl",
|
||||
};
|
||||
|
||||
+static const char* const i2s_out_y_groups[] = {
|
||||
+ "i2s_out_ch23_y", "i2s_out_ch45_y", "i2s_out_ch67_y",
|
||||
+};
|
||||
+
|
||||
static const char * const gpio_aobus_groups[] = {
|
||||
"GPIOAO_0", "GPIOAO_1", "GPIOAO_2", "GPIOAO_3", "GPIOAO_4",
|
||||
"GPIOAO_5", "GPIOAO_6", "GPIOAO_7", "GPIOAO_8", "GPIOAO_9",
|
||||
@@ -694,6 +718,11 @@
|
||||
"pwm_ao_b",
|
||||
};
|
||||
|
||||
+static const char* const i2s_out_ao_groups[] = {
|
||||
+ "i2s_am_clk", "i2s_out_ao_clk", "i2s_out_lr_clk",
|
||||
+ "i2s_out_ch01_ao", "i2s_out_ch23_ao", "i2s_out_ch45_ao",
|
||||
+};
|
||||
+
|
||||
static struct meson_pmx_func meson_gxbb_periphs_functions[] = {
|
||||
FUNCTION(gpio_periphs),
|
||||
FUNCTION(emmc),
|
||||
@@ -717,6 +746,7 @@
|
||||
FUNCTION(pwm_f_y),
|
||||
FUNCTION(hdmi_hpd),
|
||||
FUNCTION(hdmi_i2c),
|
||||
+ FUNCTION(i2s_out_y),
|
||||
};
|
||||
|
||||
static struct meson_pmx_func meson_gxbb_aobus_functions[] = {
|
||||
@@ -730,6 +760,7 @@
|
||||
FUNCTION(pwm_ao_a_6),
|
||||
FUNCTION(pwm_ao_a_12),
|
||||
FUNCTION(pwm_ao_b),
|
||||
+ FUNCTION(i2s_out_ao),
|
||||
};
|
||||
|
||||
static struct meson_bank meson_gxbb_periphs_banks[] = {
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
From b5471e9b3a9700b023c9ee1b9eb4b0a10af72427 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Thu, 26 Jan 2017 11:09:54 +0100
|
||||
Subject: [PATCH 73/93] ARM64: meson: gxbb: add i2s output pins
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
---
|
||||
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 57 +++++++++++++++++++++++++++++
|
||||
1 file changed, 57 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
index b897ad6..ea111a2 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
@@ -238,6 +238,42 @@
|
||||
function = "pwm_ao_b";
|
||||
};
|
||||
};
|
||||
+
|
||||
+ i2s_am_clk_pins: i2s_am_clk {
|
||||
+ mux {
|
||||
+ groups = "i2s_am_clk";
|
||||
+ function = "i2s_out_ao";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ i2s_out_bclks_pins: i2s_out_bclks {
|
||||
+ mux {
|
||||
+ groups = "i2s_out_ao_clk",
|
||||
+ "i2s_out_lr_clk";
|
||||
+ function = "i2s_out_ao";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ i2s_out_ch01_ao_pins: i2s_out_ch01_ao {
|
||||
+ mux {
|
||||
+ groups = "i2s_out_ch01_ao";
|
||||
+ function = "i2s_out_ao";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ i2s_out_ch23_ao_pins: i2s_out_ch23_ao {
|
||||
+ mux {
|
||||
+ groups = "i2s_out_ch23_ao";
|
||||
+ function = "i2s_out_ao";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ i2s_out_ch45_ao_pins: i2s_out_ch45_ao {
|
||||
+ mux {
|
||||
+ groups = "i2s_out_ch45_ao";
|
||||
+ function = "i2s_out_ao";
|
||||
+ };
|
||||
+ };
|
||||
};
|
||||
|
||||
clkc_AO: clock-controller@040 {
|
||||
@@ -479,6 +515,27 @@
|
||||
function = "hdmi_i2c";
|
||||
};
|
||||
};
|
||||
+
|
||||
+ i2sout_ch23_y_pins: i2sout_ch23_y {
|
||||
+ mux {
|
||||
+ groups = "i2sout_ch23_y";
|
||||
+ function = "i2s_out_y";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ i2sout_ch45_y_pins: i2sout_ch45_y {
|
||||
+ mux {
|
||||
+ groups = "i2sout_ch45_y";
|
||||
+ function = "i2s_out_y";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ i2sout_ch67_y_pins: i2sout_ch67_y {
|
||||
+ mux {
|
||||
+ groups = "i2sout_ch67_y";
|
||||
+ function = "i2s_out_y";
|
||||
+ };
|
||||
+ };
|
||||
};
|
||||
};
|
||||
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,206 @@
|
|||
From d8358b5a254018c6329d4da6fb215bcecdfbceae Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Thu, 19 Jan 2017 15:49:08 +0100
|
||||
Subject: [PATCH 74/93] snd: meson: add aiu register definitions
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
---
|
||||
sound/soc/meson/aiu-regs.h | 186 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 186 insertions(+)
|
||||
create mode 100644 sound/soc/meson/aiu-regs.h
|
||||
|
||||
diff --git a/sound/soc/meson/aiu-regs.h b/sound/soc/meson/aiu-regs.h
|
||||
new file mode 100644
|
||||
index 0000000..3b1945c
|
||||
--- /dev/null
|
||||
+++ b/sound/soc/meson/aiu-regs.h
|
||||
@@ -0,0 +1,186 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2017 BayLibre, SAS
|
||||
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
|
||||
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation; either version 2 of the
|
||||
+ * License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful, but
|
||||
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ * General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
+ */
|
||||
+
|
||||
+#ifndef _AIU_REGS_H_
|
||||
+#define _AIU_REGS_H_
|
||||
+
|
||||
+/* Base address of AIU within Cbus */
|
||||
+#define AIU_CBUS_BASE 0x5400 /* REALLY USEFUL ??? */
|
||||
+
|
||||
+/* AIU Registers */
|
||||
+#define AIU_958_BPF 0x000
|
||||
+#define AIU_958_BRST 0x004
|
||||
+#define AIU_958_LENGTH 0x008
|
||||
+#define AIU_958_PADDSIZE 0x00C
|
||||
+#define AIU_958_MISC 0x010
|
||||
+#define AIU_958_FORCE_LEFT 0x014 /* Unknown */
|
||||
+#define AIU_958_DISCARD_NUM 0x018
|
||||
+#define AIU_958_DCU_FF_CTRL 0x01C
|
||||
+#define AIU_958_CHSTAT_L0 0x020
|
||||
+#define AIU_958_CHSTAT_L1 0x024
|
||||
+#define AIU_958_CTRL 0x028
|
||||
+#define AIU_958_RPT 0x02C
|
||||
+#define AIU_I2S_MUTE_SWAP 0x030
|
||||
+#define AIU_I2S_SOURCE_DESC 0x034
|
||||
+#define AIU_I2S_MED_CTRL 0x038
|
||||
+#define AIU_I2S_MED_THRESH 0x03C
|
||||
+#define AIU_I2S_DAC_CFG 0x040
|
||||
+#define AIU_I2S_SYNC 0x044 /* Unknown */
|
||||
+#define AIU_I2S_MISC 0x048
|
||||
+#define AIU_I2S_OUT_CFG 0x04C
|
||||
+#define AIU_I2S_FF_CTRL 0x050 /* Unknown */
|
||||
+#define AIU_RST_SOFT 0x054
|
||||
+#define AIU_CLK_CTRL 0x058
|
||||
+#define AIU_MIX_ADCCFG 0x05C
|
||||
+#define AIU_MIX_CTRL 0x060
|
||||
+#define AIU_CLK_CTRL_MORE 0x064
|
||||
+#define AIU_958_POP 0x068
|
||||
+#define AIU_MIX_GAIN 0x06C
|
||||
+#define AIU_958_SYNWORD1 0x070
|
||||
+#define AIU_958_SYNWORD2 0x074
|
||||
+#define AIU_958_SYNWORD3 0x078
|
||||
+#define AIU_958_SYNWORD1_MASK 0x07C
|
||||
+#define AIU_958_SYNWORD2_MASK 0x080
|
||||
+#define AIU_958_SYNWORD3_MASK 0x084
|
||||
+#define AIU_958_FFRDOUT_THD 0x088
|
||||
+#define AIU_958_LENGTH_PER_PAUSE 0x08C
|
||||
+#define AIU_958_PAUSE_NUM 0x090
|
||||
+#define AIU_958_PAUSE_PAYLOAD 0x094
|
||||
+#define AIU_958_AUTO_PAUSE 0x098
|
||||
+#define AIU_958_PAUSE_PD_LENGTH 0x09C
|
||||
+#define AIU_CODEC_DAC_LRCLK_CTRL 0x0A0
|
||||
+#define AIU_CODEC_ADC_LRCLK_CTRL 0x0A4
|
||||
+#define AIU_HDMI_CLK_DATA_CTRL 0x0A8
|
||||
+#define AIU_CODEC_CLK_DATA_CTRL 0x0AC
|
||||
+#define AIU_ACODEC_CTRL 0x0B0 /* Unknown */
|
||||
+#define AIU_958_CHSTAT_R0 0x0C0
|
||||
+#define AIU_958_CHSTAT_R1 0x0C4
|
||||
+#define AIU_958_VALID_CTRL 0x0C8
|
||||
+#define AIU_AUDIO_AMP_REG0 0x0F0 /* Unknown */
|
||||
+#define AIU_AUDIO_AMP_REG1 0x0F4 /* Unknown */
|
||||
+#define AIU_AUDIO_AMP_REG2 0x0F8 /* Unknown */
|
||||
+#define AIU_AUDIO_AMP_REG3 0x0FC /* Unknown */
|
||||
+#define AIU_AIFIFO2_CTRL 0x100
|
||||
+#define AIU_AIFIFO2_STATUS 0x104
|
||||
+#define AIU_AIFIFO2_GBIT 0x108
|
||||
+#define AIU_AIFIFO2_CLB 0x10C
|
||||
+#define AIU_CRC_CTRL 0x110
|
||||
+#define AIU_CRC_STATUS 0x114
|
||||
+#define AIU_CRC_SHIFT_REG 0x118
|
||||
+#define AIU_CRC_IREG 0x11C
|
||||
+#define AIU_CRC_CAL_REG1 0x120
|
||||
+#define AIU_CRC_CAL_REG0 0x124
|
||||
+#define AIU_CRC_POLY_COEF1 0x128
|
||||
+#define AIU_CRC_POLY_COEF0 0x12C
|
||||
+#define AIU_CRC_BIT_SIZE1 0x130
|
||||
+#define AIU_CRC_BIT_SIZE0 0x134
|
||||
+#define AIU_CRC_BIT_CNT1 0x138
|
||||
+#define AIU_CRC_BIT_CNT0 0x13C
|
||||
+#define AIU_AMCLK_GATE_HI 0x140
|
||||
+#define AIU_AMCLK_GATE_LO 0x144
|
||||
+#define AIU_AMCLK_MSR 0x148
|
||||
+#define AIU_AUDAC_CTRL0 0x14C /* Unknown */
|
||||
+#define AIU_DELTA_SIGMA0 0x154 /* Unknown */
|
||||
+#define AIU_DELTA_SIGMA1 0x158 /* Unknown */
|
||||
+#define AIU_DELTA_SIGMA2 0x15C /* Unknown */
|
||||
+#define AIU_DELTA_SIGMA3 0x160 /* Unknown */
|
||||
+#define AIU_DELTA_SIGMA4 0x164 /* Unknown */
|
||||
+#define AIU_DELTA_SIGMA5 0x168 /* Unknown */
|
||||
+#define AIU_DELTA_SIGMA6 0x16C /* Unknown */
|
||||
+#define AIU_DELTA_SIGMA7 0x170 /* Unknown */
|
||||
+#define AIU_DELTA_SIGMA_LCNTS 0x174 /* Unknown */
|
||||
+#define AIU_DELTA_SIGMA_RCNTS 0x178 /* Unknown */
|
||||
+#define AIU_MEM_I2S_START_PTR 0x180
|
||||
+#define AIU_MEM_I2S_RD_PTR 0x184
|
||||
+#define AIU_MEM_I2S_END_PTR 0x188
|
||||
+#define AIU_MEM_I2S_MASKS 0x18C
|
||||
+#define AIU_MEM_I2S_CONTROL 0x190
|
||||
+#define AIU_MEM_IEC958_START_PTR 0x194
|
||||
+#define AIU_MEM_IEC958_RD_PTR 0x198
|
||||
+#define AIU_MEM_IEC958_END_PTR 0x19C
|
||||
+#define AIU_MEM_IEC958_MASKS 0x1A0
|
||||
+#define AIU_MEM_IEC958_CONTROL 0x1A4
|
||||
+#define AIU_MEM_AIFIFO2_START_PTR 0x1A8
|
||||
+#define AIU_MEM_AIFIFO2_CURR_PTR 0x1AC
|
||||
+#define AIU_MEM_AIFIFO2_END_PTR 0x1B0
|
||||
+#define AIU_MEM_AIFIFO2_BYTES_AVAIL 0x1B4
|
||||
+#define AIU_MEM_AIFIFO2_CONTROL 0x1B8
|
||||
+#define AIU_MEM_AIFIFO2_MAN_WP 0x1BC
|
||||
+#define AIU_MEM_AIFIFO2_MAN_RP 0x1C0
|
||||
+#define AIU_MEM_AIFIFO2_LEVEL 0x1C4
|
||||
+#define AIU_MEM_AIFIFO2_BUF_CNTL 0x1C8
|
||||
+#define AIU_MEM_I2S_MAN_WP 0x1CC
|
||||
+#define AIU_MEM_I2S_MAN_RP 0x1D0
|
||||
+#define AIU_MEM_I2S_LEVEL 0x1D4
|
||||
+#define AIU_MEM_I2S_BUF_CNTL 0x1D8
|
||||
+#define AIU_MEM_I2S_BUF_WRAP_COUNT 0x1DC
|
||||
+#define AIU_MEM_I2S_MEM_CTL 0x1E0
|
||||
+#define AIU_MEM_IEC958_MEM_CTL 0x1E4
|
||||
+#define AIU_MEM_IEC958_WRAP_COUNT 0x1E8
|
||||
+#define AIU_MEM_IEC958_IRQ_LEVEL 0x1EC
|
||||
+#define AIU_MEM_IEC958_MAN_WP 0x1F0
|
||||
+#define AIU_MEM_IEC958_MAN_RP 0x1F4
|
||||
+#define AIU_MEM_IEC958_LEVEL 0x1F8
|
||||
+#define AIU_MEM_IEC958_BUF_CNTL 0x1FC
|
||||
+#define AIU_AIFIFO_CTRL 0x200
|
||||
+#define AIU_AIFIFO_STATUS 0x204
|
||||
+#define AIU_AIFIFO_GBIT 0x208
|
||||
+#define AIU_AIFIFO_CLB 0x20C
|
||||
+#define AIU_MEM_AIFIFO_START_PTR 0x210
|
||||
+#define AIU_MEM_AIFIFO_CURR_PTR 0x214
|
||||
+#define AIU_MEM_AIFIFO_END_PTR 0x218
|
||||
+#define AIU_MEM_AIFIFO_BYTES_AVAIL 0x21C
|
||||
+#define AIU_MEM_AIFIFO_CONTROL 0x220
|
||||
+#define AIU_MEM_AIFIFO_MAN_WP 0x224
|
||||
+#define AIU_MEM_AIFIFO_MAN_RP 0x228
|
||||
+#define AIU_MEM_AIFIFO_LEVEL 0x22C
|
||||
+#define AIU_MEM_AIFIFO_BUF_CNTL 0x230
|
||||
+#define AIU_MEM_AIFIFO_BUF_WRAP_COUNT 0x234
|
||||
+#define AIU_MEM_AIFIFO2_BUF_WRAP_COUNT 0x238
|
||||
+#define AIU_MEM_AIFIFO_MEM_CTL 0x23C
|
||||
+#define AIFIFO_TIME_STAMP_CNTL 0x240
|
||||
+#define AIFIFO_TIME_STAMP_SYNC_0 0x244
|
||||
+#define AIFIFO_TIME_STAMP_SYNC_1 0x248
|
||||
+#define AIFIFO_TIME_STAMP_0 0x24C
|
||||
+#define AIFIFO_TIME_STAMP_1 0x250
|
||||
+#define AIFIFO_TIME_STAMP_2 0x254
|
||||
+#define AIFIFO_TIME_STAMP_3 0x258
|
||||
+#define AIFIFO_TIME_STAMP_LENGTH 0x25C
|
||||
+#define AIFIFO2_TIME_STAMP_CNTL 0x260
|
||||
+#define AIFIFO2_TIME_STAMP_SYNC_0 0x264
|
||||
+#define AIFIFO2_TIME_STAMP_SYNC_1 0x268
|
||||
+#define AIFIFO2_TIME_STAMP_0 0x26C
|
||||
+#define AIFIFO2_TIME_STAMP_1 0x270
|
||||
+#define AIFIFO2_TIME_STAMP_2 0x274
|
||||
+#define AIFIFO2_TIME_STAMP_3 0x278
|
||||
+#define AIFIFO2_TIME_STAMP_LENGTH 0x27C
|
||||
+#define IEC958_TIME_STAMP_CNTL 0x280
|
||||
+#define IEC958_TIME_STAMP_SYNC_0 0x284
|
||||
+#define IEC958_TIME_STAMP_SYNC_1 0x288
|
||||
+#define IEC958_TIME_STAMP_0 0x28C
|
||||
+#define IEC958_TIME_STAMP_1 0x290
|
||||
+#define IEC958_TIME_STAMP_2 0x294
|
||||
+#define IEC958_TIME_STAMP_3 0x298
|
||||
+#define IEC958_TIME_STAMP_LENGTH 0x29C
|
||||
+#define AIU_MEM_AIFIFO2_MEM_CTL 0x2A0
|
||||
+#define AIU_I2S_CBUS_DDR_CNTL 0x2A4
|
||||
+#define AIU_I2S_CBUS_DDR_WDATA 0x2A8
|
||||
+#define AIU_I2S_CBUS_DDR_ADDR 0x2AC
|
||||
+
|
||||
+#endif /* _AIU_REGS_H_ */
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,172 @@
|
|||
From 788001e5eb1bab1464a9f6e97e5619f3994ff5ba Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Thu, 19 Jan 2017 15:49:39 +0100
|
||||
Subject: [PATCH 75/93] snd: meson: add audin register definitions
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
---
|
||||
sound/soc/meson/audin-regs.h | 152 +++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 152 insertions(+)
|
||||
create mode 100644 sound/soc/meson/audin-regs.h
|
||||
|
||||
diff --git a/sound/soc/meson/audin-regs.h b/sound/soc/meson/audin-regs.h
|
||||
new file mode 100644
|
||||
index 0000000..f6f3203
|
||||
--- /dev/null
|
||||
+++ b/sound/soc/meson/audin-regs.h
|
||||
@@ -0,0 +1,152 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2017 BayLibre, SAS
|
||||
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
|
||||
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation; either version 2 of the
|
||||
+ * License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful, but
|
||||
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ * General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
+ */
|
||||
+
|
||||
+#ifndef _AUDIN_REGS_H_
|
||||
+#define _AUDIN_REGS_H_
|
||||
+
|
||||
+/* Base address of Audio In module in Cbus */
|
||||
+#define AUDIN_CBUS_BASE 0xA000 /* REALLY USEFUL ??? */
|
||||
+
|
||||
+/*
|
||||
+ * Note :
|
||||
+ * Datasheet issue page 196
|
||||
+ * AUDIN_MUTE_VAL 0x35 => impossible: Already assigned to AUDIN_FIFO1_PTR
|
||||
+ * AUDIN_FIFO1_PTR is more likely to be correct since surrounding registers
|
||||
+ * also deal with AUDIN_FIFO1
|
||||
+ *
|
||||
+ * Clarification needed from Amlogic
|
||||
+ */
|
||||
+
|
||||
+/* Audin module registers */
|
||||
+#define AUDIN_SPDIF_MODE 0x000
|
||||
+#define AUDIN_SPDIF_FS_CLK_RLTN 0x004
|
||||
+#define AUDIN_SPDIF_CHNL_STS_A 0x008
|
||||
+#define AUDIN_SPDIF_CHNL_STS_B 0x00C
|
||||
+#define AUDIN_SPDIF_MISC 0x010
|
||||
+#define AUDIN_SPDIF_NPCM_PCPD 0x014
|
||||
+#define AUDIN_SPDIF_END 0x03C /* Unknown */
|
||||
+#define AUDIN_I2SIN_CTRL 0x040
|
||||
+#define AUDIN_SOURCE_SEL 0x044
|
||||
+#define AUDIN_DECODE_FORMAT 0x048
|
||||
+#define AUDIN_DECODE_CONTROL_STATUS 0x04C
|
||||
+#define AUDIN_DECODE_CHANNEL_STATUS_A_0 0x050
|
||||
+#define AUDIN_DECODE_CHANNEL_STATUS_A_1 0x054
|
||||
+#define AUDIN_DECODE_CHANNEL_STATUS_A_2 0x058
|
||||
+#define AUDIN_DECODE_CHANNEL_STATUS_A_3 0x05C
|
||||
+#define AUDIN_DECODE_CHANNEL_STATUS_A_4 0x060
|
||||
+#define AUDIN_DECODE_CHANNEL_STATUS_A_5 0x064
|
||||
+#define AUDIN_FIFO0_START 0x080
|
||||
+#define AUDIN_FIFO0_END 0x084
|
||||
+#define AUDIN_FIFO0_PTR 0x088
|
||||
+#define AUDIN_FIFO0_INTR 0x08C
|
||||
+#define AUDIN_FIFO0_RDPTR 0x090
|
||||
+#define AUDIN_FIFO0_CTRL 0x094
|
||||
+#define AUDIN_FIFO0_CTRL1 0x098
|
||||
+#define AUDIN_FIFO0_LVL0 0x09C
|
||||
+#define AUDIN_FIFO0_LVL1 0x0A0
|
||||
+#define AUDIN_FIFO0_LVL2 0x0A4
|
||||
+#define AUDIN_FIFO0_REQID 0x0C0
|
||||
+#define AUDIN_FIFO0_WRAP 0x0C4
|
||||
+#define AUDIN_FIFO1_START 0x0CC
|
||||
+#define AUDIN_FIFO1_END 0x0D0
|
||||
+#define AUDIN_FIFO1_PTR 0x0D4
|
||||
+#define AUDIN_FIFO1_INTR 0x0D8
|
||||
+#define AUDIN_FIFO1_RDPTR 0x0DC
|
||||
+#define AUDIN_FIFO1_CTRL 0x0E0
|
||||
+#define AUDIN_FIFO1_CTRL1 0x0E4
|
||||
+#define AUDIN_FIFO1_LVL0 0x100
|
||||
+#define AUDIN_FIFO1_LVL1 0x104
|
||||
+#define AUDIN_FIFO1_LVL2 0x108
|
||||
+#define AUDIN_FIFO1_REQID 0x10C
|
||||
+#define AUDIN_FIFO1_WRAP 0x110
|
||||
+#define AUDIN_FIFO2_START 0x114
|
||||
+#define AUDIN_FIFO2_END 0x118
|
||||
+#define AUDIN_FIFO2_PTR 0x11C
|
||||
+#define AUDIN_FIFO2_INTR 0x120
|
||||
+#define AUDIN_FIFO2_RDPTR 0x124
|
||||
+#define AUDIN_FIFO2_CTRL 0x128
|
||||
+#define AUDIN_FIFO2_CTRL1 0x12C
|
||||
+#define AUDIN_FIFO2_LVL0 0x130
|
||||
+#define AUDIN_FIFO2_LVL1 0x134
|
||||
+#define AUDIN_FIFO2_LVL2 0x138
|
||||
+#define AUDIN_FIFO2_REQID 0x13C
|
||||
+#define AUDIN_FIFO2_WRAP 0x140
|
||||
+#define AUDIN_INT_CTRL 0x144
|
||||
+#define AUDIN_FIFO_INT 0x148
|
||||
+#define PCMIN_CTRL0 0x180
|
||||
+#define PCMIN_CTRL1 0x184
|
||||
+#define PCMIN1_CTRL0 0x188
|
||||
+#define PCMIN1_CTRL1 0x18C
|
||||
+#define PCMOUT_CTRL0 0x1C0
|
||||
+#define PCMOUT_CTRL1 0x1C4
|
||||
+#define PCMOUT_CTRL2 0x1C8
|
||||
+#define PCMOUT_CTRL3 0x1CC
|
||||
+#define PCMOUT1_CTRL0 0x1D0
|
||||
+#define PCMOUT1_CTRL1 0x1D4
|
||||
+#define PCMOUT1_CTRL2 0x1D8
|
||||
+#define PCMOUT1_CTRL3 0x1DC
|
||||
+#define AUDOUT_CTRL 0x200
|
||||
+#define AUDOUT_CTRL1 0x204
|
||||
+#define AUDOUT_BUF0_STA 0x208
|
||||
+#define AUDOUT_BUF0_EDA 0x20C
|
||||
+#define AUDOUT_BUF0_WPTR 0x210
|
||||
+#define AUDOUT_BUF1_STA 0x214
|
||||
+#define AUDOUT_BUF1_EDA 0x218
|
||||
+#define AUDOUT_BUF1_WPTR 0x21C
|
||||
+#define AUDOUT_FIFO_RPTR 0x220
|
||||
+#define AUDOUT_INTR_PTR 0x224
|
||||
+#define AUDOUT_FIFO_STS 0x228
|
||||
+#define AUDOUT1_CTRL 0x240
|
||||
+#define AUDOUT1_CTRL1 0x244
|
||||
+#define AUDOUT1_BUF0_STA 0x248
|
||||
+#define AUDOUT1_BUF0_EDA 0x24C
|
||||
+#define AUDOUT1_BUF0_WPTR 0x250
|
||||
+#define AUDOUT1_BUF1_STA 0x254
|
||||
+#define AUDOUT1_BUF1_EDA 0x258
|
||||
+#define AUDOUT1_BUF1_WPTR 0x25C
|
||||
+#define AUDOUT1_FIFO_RPTR 0x260
|
||||
+#define AUDOUT1_INTR_PTR 0x264
|
||||
+#define AUDOUT1_FIFO_STS 0x268
|
||||
+#define AUDIN_HDMI_MEAS_CTRL 0x280
|
||||
+#define AUDIN_HDMI_MEAS_CYCLES_M1 0x284
|
||||
+#define AUDIN_HDMI_MEAS_INTR_MASKN 0x288
|
||||
+#define AUDIN_HDMI_MEAS_INTR_STAT 0x28C
|
||||
+#define AUDIN_HDMI_REF_CYCLES_STAT_0 0x290
|
||||
+#define AUDIN_HDMI_REF_CYCLES_STAT_1 0x294
|
||||
+#define AUDIN_HDMIRX_AFIFO_STAT 0x298
|
||||
+#define AUDIN_FIFO0_PIO_STS 0x2C0
|
||||
+#define AUDIN_FIFO0_PIO_RDL 0x2C4
|
||||
+#define AUDIN_FIFO0_PIO_RDH 0x2C8
|
||||
+#define AUDIN_FIFO1_PIO_STS 0x2CC
|
||||
+#define AUDIN_FIFO1_PIO_RDL 0x2D0
|
||||
+#define AUDIN_FIFO1_PIO_RDH 0x2D4
|
||||
+#define AUDIN_FIFO2_PIO_STS 0x2D8
|
||||
+#define AUDIN_FIFO2_PIO_RDL 0x2DC
|
||||
+#define AUDIN_FIFO2_PIO_RDH 0x2E0
|
||||
+#define AUDOUT_FIFO_PIO_STS 0x2E4
|
||||
+#define AUDOUT_FIFO_PIO_WRL 0x2E8
|
||||
+#define AUDOUT_FIFO_PIO_WRH 0x2EC
|
||||
+#define AUDOUT1_FIFO_PIO_STS 0x2F0 /* Unknown */
|
||||
+#define AUDOUT1_FIFO_PIO_WRL 0x2F4 /* Unknown */
|
||||
+#define AUDOUT1_FIFO_PIO_WRH 0x2F8 /* Unknown */
|
||||
+#define AUD_RESAMPLE_CTRL0 0x2FC
|
||||
+#define AUD_RESAMPLE_CTRL1 0x300
|
||||
+#define AUD_RESAMPLE_STATUS 0x304
|
||||
+
|
||||
+#endif /* _AUDIN_REGS_H_ */
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,575 @@
|
|||
From 0a351cf435e75a028694a7d5782f2b46582b004d Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Sun, 12 Feb 2017 00:50:07 +0100
|
||||
Subject: [PATCH 76/93] snd: soc: meson: support for aiu i2s dma
|
||||
|
||||
Initial support for meson aiu i2s dma
|
||||
TO BE COMPLETED ...
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
---
|
||||
sound/soc/Kconfig | 1 +
|
||||
sound/soc/Makefile | 1 +
|
||||
sound/soc/meson/Kconfig | 17 ++
|
||||
sound/soc/meson/Makefile | 2 +
|
||||
sound/soc/meson/aiu-common.c | 69 ++++++++
|
||||
sound/soc/meson/aiu-i2s-dma.c | 400 ++++++++++++++++++++++++++++++++++++++++++
|
||||
sound/soc/meson/aiu.h | 6 +
|
||||
7 files changed, 496 insertions(+)
|
||||
create mode 100644 sound/soc/meson/Kconfig
|
||||
create mode 100644 sound/soc/meson/Makefile
|
||||
create mode 100644 sound/soc/meson/aiu-common.c
|
||||
create mode 100644 sound/soc/meson/aiu-i2s-dma.c
|
||||
create mode 100644 sound/soc/meson/aiu.h
|
||||
|
||||
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
|
||||
index 182d92e..58ed5cf 100644
|
||||
--- a/sound/soc/Kconfig
|
||||
+++ b/sound/soc/Kconfig
|
||||
@@ -54,6 +54,7 @@ source "sound/soc/kirkwood/Kconfig"
|
||||
source "sound/soc/img/Kconfig"
|
||||
source "sound/soc/intel/Kconfig"
|
||||
source "sound/soc/mediatek/Kconfig"
|
||||
+source "sound/soc/meson/Kconfig"
|
||||
source "sound/soc/mxs/Kconfig"
|
||||
source "sound/soc/pxa/Kconfig"
|
||||
source "sound/soc/qcom/Kconfig"
|
||||
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
|
||||
index 9a30f21..fbe16ac 100644
|
||||
--- a/sound/soc/Makefile
|
||||
+++ b/sound/soc/Makefile
|
||||
@@ -31,6 +31,7 @@ obj-$(CONFIG_SND_SOC) += jz4740/
|
||||
obj-$(CONFIG_SND_SOC) += img/
|
||||
obj-$(CONFIG_SND_SOC) += intel/
|
||||
obj-$(CONFIG_SND_SOC) += mediatek/
|
||||
+obj-$(CONFIG_SND_SOC) += meson/
|
||||
obj-$(CONFIG_SND_SOC) += mxs/
|
||||
obj-$(CONFIG_SND_SOC) += nuc900/
|
||||
obj-$(CONFIG_SND_SOC) += omap/
|
||||
diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig
|
||||
new file mode 100644
|
||||
index 0000000..f2504c6
|
||||
--- /dev/null
|
||||
+++ b/sound/soc/meson/Kconfig
|
||||
@@ -0,0 +1,17 @@
|
||||
+menu "Amlogic SoC Audio Support"
|
||||
+ depends on ARCH_MESON || COMPILE_TEST
|
||||
+
|
||||
+config SND_MESON_AIU_I2S_DMA
|
||||
+ tristate "Meson I2S Output DMA Support"
|
||||
+ select MFD_SYSCON
|
||||
+ select SND_MESON_AIU_COMMON
|
||||
+ help
|
||||
+ This adds ASoC driver the Amlogic Meson i2s DAI
|
||||
+ If unsure select "N".
|
||||
+
|
||||
+endmenu
|
||||
+
|
||||
+config SND_MESON_AIU_COMMON
|
||||
+ tristate
|
||||
+ depends on ARCH_MESON
|
||||
+ depends on REGMAP_MMIO
|
||||
diff --git a/sound/soc/meson/Makefile b/sound/soc/meson/Makefile
|
||||
new file mode 100644
|
||||
index 0000000..b237894
|
||||
--- /dev/null
|
||||
+++ b/sound/soc/meson/Makefile
|
||||
@@ -0,0 +1,2 @@
|
||||
+obj-$(CONFIG_SND_MESON_AIU_COMMON) += aiu-common.o
|
||||
+obj-$(CONFIG_SND_MESON_AIU_I2S_DMA) += aiu-i2s-dma.o
|
||||
diff --git a/sound/soc/meson/aiu-common.c b/sound/soc/meson/aiu-common.c
|
||||
new file mode 100644
|
||||
index 0000000..9beee94
|
||||
--- /dev/null
|
||||
+++ b/sound/soc/meson/aiu-common.c
|
||||
@@ -0,0 +1,69 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2017 BayLibre, SAS
|
||||
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
|
||||
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation; either version 2 of the
|
||||
+ * License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful, but
|
||||
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ * General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+
|
||||
+
|
||||
+static const char* aiu_gate_names[] = { "aiu_top", "aiu_glue" };
|
||||
+
|
||||
+static int aiu_common_register_clk_gates(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct clk *gate;
|
||||
+ int i, ret;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(aiu_gate_names); i++) {
|
||||
+ gate = devm_clk_get(dev, aiu_gate_names[i]);
|
||||
+ if (IS_ERR(gate)) {
|
||||
+ if (PTR_ERR(gate) != -EPROBE_DEFER)
|
||||
+ dev_err(dev, "Failed to get %s clock gate\n",
|
||||
+ aiu_gate_names[i]);
|
||||
+ return PTR_ERR(gate);
|
||||
+ }
|
||||
+
|
||||
+ ret = clk_prepare_enable(gate);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev, "failed to enable %s clock gate\n",
|
||||
+ aiu_gate_names[i]);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int aiu_common_register(struct platform_device *pdev)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = aiu_common_register_clk_gates(pdev);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* FIXME: We should also handle the AIU reset here */
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(aiu_common_register);
|
||||
+
|
||||
+MODULE_DESCRIPTION("Meson AIU common helper");
|
||||
+MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
|
||||
+MODULE_LICENSE("GPL v2");
|
||||
diff --git a/sound/soc/meson/aiu-i2s-dma.c b/sound/soc/meson/aiu-i2s-dma.c
|
||||
new file mode 100644
|
||||
index 0000000..1e8886c
|
||||
--- /dev/null
|
||||
+++ b/sound/soc/meson/aiu-i2s-dma.c
|
||||
@@ -0,0 +1,400 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2017 BayLibre, SAS
|
||||
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
|
||||
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation; either version 2 of the
|
||||
+ * License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful, but
|
||||
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ * General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
+ */
|
||||
+
|
||||
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
+
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/mfd/syscon.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/regmap.h>
|
||||
+
|
||||
+#include <sound/pcm_params.h>
|
||||
+#include <sound/soc.h>
|
||||
+
|
||||
+#include "aiu.h"
|
||||
+#include "aiu-regs.h"
|
||||
+
|
||||
+#define DRV_NAME "meson-aiu-i2s-dma"
|
||||
+
|
||||
+struct aiu_i2s_dma {
|
||||
+ struct regmap* regmap;
|
||||
+
|
||||
+ struct clk* i2s_out;
|
||||
+
|
||||
+ int irq;
|
||||
+};
|
||||
+
|
||||
+#define AIU_MEM_I2S_BUF_CNTL_INIT BIT(0)
|
||||
+#define AIU_MEM_I2S_CONTROL_INIT BIT(0)
|
||||
+#define AIU_MEM_I2S_CONTROL_FILL_EN BIT(1)
|
||||
+#define AIU_MEM_I2S_CONTROL_EMPTY_EN BIT(2)
|
||||
+#define AIU_MEM_I2S_CONTROL_MODE_16BIT BIT(6)
|
||||
+#define AIU_MEM_I2S_CONTROL_BUSY BIT(7)
|
||||
+#define AIU_MEM_I2S_CONTROL_DATA_READY BIT(8)
|
||||
+#define AIU_MEM_I2S_CONTROL_LEVEL_CNTL BIT(9)
|
||||
+#define AIU_MEM_I2S_MASKS_IRQ_BLOCK_MASK GENMASK(31, 16)
|
||||
+#define AIU_MEM_I2S_MASKS_IRQ_BLOCK(n) ((n) << 16)
|
||||
+#define AIU_MEM_I2S_MASKS_CH_MEM_MASK GENMASK(15, 8)
|
||||
+#define AIU_MEM_I2S_MASKS_CH_MEM(ch) ((ch) << 8)
|
||||
+#define AIU_MEM_I2S_MASKS_CH_RD_MASK GENMASK(7, 0)
|
||||
+#define AIU_MEM_I2S_MASKS_CH_RD(ch) ((ch) << 0)
|
||||
+#define AIU_RST_SOFT_I2S_FAST_DOMAIN BIT(0)
|
||||
+#define AIU_RST_SOFT_I2S_SLOW_DOMAIN BIT(1)
|
||||
+#define AIU_I2S_SOURCE_DESC_MODE_8CH BIT(0)
|
||||
+#define AIU_I2S_SOURCE_DESC_MODE_24BIT BIT(5)
|
||||
+#define AIU_I2S_SOURCE_DESC_MODE_32BIT BIT(9)
|
||||
+#define AIU_I2S_SOURCE_DESC_MODE_SPLIT BIT(11)
|
||||
+
|
||||
+/*
|
||||
+ * The DMA works by i2s "blocks" (or DMA burst). The burst size and the memory
|
||||
+ * layout expected depends on the mode of operation.
|
||||
+ *
|
||||
+ * - Normal mode:
|
||||
+ * The channels are expected to be packed in 32 bytes groups interleaved the
|
||||
+ * buffer. AIU_MEM_I2S_MASKS_CH_MEM is a bitfield representing the channels
|
||||
+ * present in memory. AIU_MEM_I2S_MASKS_CH_MEM represents the channels read by
|
||||
+ * the DMA. This very flexible but the unsual memory layout makes it less easy
|
||||
+ * to deal with. The burst size is 32 bytes times the number of channels read.
|
||||
+ *
|
||||
+ * - Split mode:
|
||||
+ * Classical channel interleaved frame organisation. In this mode,
|
||||
+ * AIU_MEM_I2S_MASKS_CH_MEM and AIU_MEM_I2S_MASKS_CH_MEM must be set to 0xff and
|
||||
+ * the burst size is fixed to 256 bytes. The input can be either 2 or 8
|
||||
+ * channels.
|
||||
+ *
|
||||
+ * The following driver implements the split mode.
|
||||
+ */
|
||||
+
|
||||
+#define AIU_I2S_DMA_BURST 256
|
||||
+
|
||||
+static struct snd_pcm_hardware aiu_i2s_dma_hw = {
|
||||
+ .info = (SNDRV_PCM_INFO_INTERLEAVED |
|
||||
+ SNDRV_PCM_INFO_MMAP |
|
||||
+ SNDRV_PCM_INFO_MMAP_VALID |
|
||||
+ SNDRV_PCM_INFO_PAUSE),
|
||||
+
|
||||
+ .formats = (SNDRV_PCM_FMTBIT_S16_LE |
|
||||
+ SNDRV_PCM_FMTBIT_S24_LE |
|
||||
+ SNDRV_PCM_FMTBIT_S32_LE),
|
||||
+
|
||||
+ /*
|
||||
+ * TODO: The DMA can change the endianness, the msb position
|
||||
+ * and deal with unsigned - support this later on
|
||||
+ */
|
||||
+
|
||||
+ .rate_min = 8000,
|
||||
+ .rate_max = 192000,
|
||||
+ .channels_min = 2,
|
||||
+ .channels_max = 8,
|
||||
+ .period_bytes_min = AIU_I2S_DMA_BURST,
|
||||
+ .period_bytes_max = AIU_I2S_DMA_BURST * 65535, /* 8192, */
|
||||
+ .periods_min = 2,
|
||||
+ .periods_max = UINT_MAX,
|
||||
+ .buffer_bytes_max = 1* 1024 * 1024,
|
||||
+ .fifo_size = 0,
|
||||
+};
|
||||
+
|
||||
+static struct aiu_i2s_dma *aiu_i2s_dma_priv(struct snd_pcm_substream *s)
|
||||
+{
|
||||
+ struct snd_soc_pcm_runtime *rtd = s->private_data;
|
||||
+ return snd_soc_platform_get_drvdata(rtd->platform);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static snd_pcm_uframes_t
|
||||
+aiu_i2s_dma_pointer(struct snd_pcm_substream *substream)
|
||||
+{
|
||||
+ struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
+ struct aiu_i2s_dma *priv = aiu_i2s_dma_priv(substream);
|
||||
+ unsigned int addr;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = regmap_read(priv->regmap, AIU_MEM_I2S_RD_PTR,
|
||||
+ &addr);
|
||||
+ if (ret)
|
||||
+ return 0;
|
||||
+
|
||||
+ return bytes_to_frames(runtime, addr - (unsigned int)runtime->dma_addr);
|
||||
+}
|
||||
+
|
||||
+static void __dma_enable(struct aiu_i2s_dma *priv, bool enable)
|
||||
+{
|
||||
+ unsigned int en_mask = (AIU_MEM_I2S_CONTROL_FILL_EN |
|
||||
+ AIU_MEM_I2S_CONTROL_EMPTY_EN);
|
||||
+
|
||||
+ regmap_update_bits(priv->regmap, AIU_MEM_I2S_CONTROL, en_mask,
|
||||
+ enable ? en_mask : 0);
|
||||
+
|
||||
+}
|
||||
+
|
||||
+static int aiu_i2s_dma_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||
+{
|
||||
+ struct aiu_i2s_dma *priv = aiu_i2s_dma_priv(substream);
|
||||
+
|
||||
+ switch (cmd) {
|
||||
+ case SNDRV_PCM_TRIGGER_START:
|
||||
+ case SNDRV_PCM_TRIGGER_RESUME:
|
||||
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||
+ __dma_enable(priv, true);
|
||||
+ break;
|
||||
+ case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||
+ case SNDRV_PCM_TRIGGER_STOP:
|
||||
+ __dma_enable(priv, false);
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void __dma_init_mem(struct aiu_i2s_dma *priv)
|
||||
+{
|
||||
+ regmap_update_bits(priv->regmap, AIU_MEM_I2S_CONTROL,
|
||||
+ AIU_MEM_I2S_CONTROL_INIT,
|
||||
+ AIU_MEM_I2S_CONTROL_INIT);
|
||||
+ regmap_update_bits(priv->regmap, AIU_MEM_I2S_BUF_CNTL,
|
||||
+ AIU_MEM_I2S_BUF_CNTL_INIT,
|
||||
+ AIU_MEM_I2S_BUF_CNTL_INIT);
|
||||
+
|
||||
+ regmap_update_bits(priv->regmap, AIU_MEM_I2S_CONTROL,
|
||||
+ AIU_MEM_I2S_CONTROL_INIT,
|
||||
+ 0);
|
||||
+ regmap_update_bits(priv->regmap, AIU_MEM_I2S_BUF_CNTL,
|
||||
+ AIU_MEM_I2S_BUF_CNTL_INIT,
|
||||
+ 0);
|
||||
+}
|
||||
+
|
||||
+static int aiu_i2s_dma_prepare(struct snd_pcm_substream *substream)
|
||||
+{
|
||||
+ struct aiu_i2s_dma *priv = aiu_i2s_dma_priv(substream);
|
||||
+
|
||||
+ __dma_init_mem(priv);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int aiu_i2s_dma_hw_params(struct snd_pcm_substream *substream,
|
||||
+ struct snd_pcm_hw_params *params)
|
||||
+{
|
||||
+ struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
+ struct aiu_i2s_dma *priv = aiu_i2s_dma_priv(substream);
|
||||
+ int ret;
|
||||
+ u32 burst_num, desc = 0, mem_ctl = 0;
|
||||
+ dma_addr_t end_ptr;
|
||||
+
|
||||
+ ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Setup memory layout */
|
||||
+ if (params_physical_width(params) == 16) {
|
||||
+ mem_ctl |= AIU_MEM_I2S_CONTROL_MODE_16BIT;
|
||||
+ } else {
|
||||
+ desc |= AIU_I2S_SOURCE_DESC_MODE_24BIT;
|
||||
+ desc |= AIU_I2S_SOURCE_DESC_MODE_32BIT;
|
||||
+ }
|
||||
+
|
||||
+ switch (params_channels(params)) {
|
||||
+ case 2: /* Nothing to do */
|
||||
+ break;
|
||||
+ case 8:
|
||||
+ desc |= AIU_I2S_SOURCE_DESC_MODE_8CH;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ /* Enable split mode - samples interleaved */
|
||||
+ desc |= AIU_I2S_SOURCE_DESC_MODE_SPLIT;
|
||||
+
|
||||
+ regmap_update_bits(priv->regmap, AIU_MEM_I2S_CONTROL,
|
||||
+ AIU_MEM_I2S_CONTROL_MODE_16BIT,
|
||||
+ mem_ctl);
|
||||
+
|
||||
+ regmap_update_bits(priv->regmap, AIU_I2S_SOURCE_DESC,
|
||||
+ AIU_I2S_SOURCE_DESC_MODE_8CH |
|
||||
+ AIU_I2S_SOURCE_DESC_MODE_24BIT |
|
||||
+ AIU_I2S_SOURCE_DESC_MODE_32BIT |
|
||||
+ AIU_I2S_SOURCE_DESC_MODE_SPLIT,
|
||||
+ desc);
|
||||
+
|
||||
+ /* Initialize memory pointers */
|
||||
+ regmap_write(priv->regmap, AIU_MEM_I2S_START_PTR, runtime->dma_addr);
|
||||
+ regmap_write(priv->regmap, AIU_MEM_I2S_RD_PTR, runtime->dma_addr);
|
||||
+
|
||||
+ /* The end pointer is the address of the last valid block */
|
||||
+ end_ptr = runtime->dma_addr + runtime->dma_bytes - AIU_I2S_DMA_BURST;
|
||||
+ regmap_write(priv->regmap, AIU_MEM_I2S_END_PTR, end_ptr);
|
||||
+
|
||||
+ /* Memory masks */
|
||||
+ burst_num = params_period_bytes(params) / AIU_I2S_DMA_BURST;
|
||||
+ regmap_write(priv->regmap, AIU_MEM_I2S_MASKS,
|
||||
+ AIU_MEM_I2S_MASKS_CH_RD(0xff) |
|
||||
+ AIU_MEM_I2S_MASKS_CH_MEM(0xff) |
|
||||
+ AIU_MEM_I2S_MASKS_IRQ_BLOCK(burst_num));
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int aiu_i2s_dma_hw_free(struct snd_pcm_substream *substream)
|
||||
+{
|
||||
+ return snd_pcm_lib_free_pages(substream);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static irqreturn_t aiu_i2s_dma_irq_block(int irq, void *dev_id)
|
||||
+{
|
||||
+ struct snd_pcm_substream *playback = dev_id;
|
||||
+
|
||||
+ snd_pcm_period_elapsed(playback);
|
||||
+
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
+
|
||||
+static int aiu_i2s_dma_open(struct snd_pcm_substream *substream)
|
||||
+{
|
||||
+ struct aiu_i2s_dma *priv = aiu_i2s_dma_priv(substream);
|
||||
+ int ret;
|
||||
+
|
||||
+ snd_soc_set_runtime_hwparams(substream, &aiu_i2s_dma_hw);
|
||||
+
|
||||
+ /*
|
||||
+ * Make sure the buffer and period size are multiple of the DMA burst
|
||||
+ * size
|
||||
+ */
|
||||
+ ret = snd_pcm_hw_constraint_step(substream->runtime, 0,
|
||||
+ SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
|
||||
+ AIU_I2S_DMA_BURST);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = snd_pcm_hw_constraint_step(substream->runtime, 0,
|
||||
+ SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
|
||||
+ AIU_I2S_DMA_BURST);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Request the I2S DDR irq */
|
||||
+ ret = request_irq(priv->irq, aiu_i2s_dma_irq_block, 0,
|
||||
+ "meson-aiu-i2s-block", substream);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Enable the DDR to FIFO clock gate */
|
||||
+ return clk_prepare_enable(priv->i2s_out);
|
||||
+}
|
||||
+
|
||||
+static int aiu_i2s_dma_close(struct snd_pcm_substream *substream)
|
||||
+{
|
||||
+ struct aiu_i2s_dma *priv = aiu_i2s_dma_priv(substream);
|
||||
+
|
||||
+ /* First close the clock gate so the DMA is definitely halted */
|
||||
+ clk_disable_unprepare(priv->i2s_out);
|
||||
+
|
||||
+ /* Free the irq */
|
||||
+ free_irq(priv->irq, substream);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct snd_pcm_ops aiu_i2s_dma_ops = {
|
||||
+ .open = aiu_i2s_dma_open,
|
||||
+ .close = aiu_i2s_dma_close,
|
||||
+ .ioctl = snd_pcm_lib_ioctl,
|
||||
+ .hw_params = aiu_i2s_dma_hw_params,
|
||||
+ .hw_free = aiu_i2s_dma_hw_free,
|
||||
+ .prepare = aiu_i2s_dma_prepare,
|
||||
+ .pointer = aiu_i2s_dma_pointer,
|
||||
+ .trigger = aiu_i2s_dma_trigger,
|
||||
+};
|
||||
+
|
||||
+static int aiu_i2s_dma_new(struct snd_soc_pcm_runtime *rtd)
|
||||
+{
|
||||
+ struct snd_card *card = rtd->card->snd_card;
|
||||
+ size_t size = aiu_i2s_dma_hw.buffer_bytes_max;
|
||||
+
|
||||
+ return snd_pcm_lib_preallocate_pages_for_all(rtd->pcm,
|
||||
+ SNDRV_DMA_TYPE_DEV,
|
||||
+ card->dev, size, size);
|
||||
+}
|
||||
+
|
||||
+struct snd_soc_platform_driver aiu_i2s_platform = {
|
||||
+ .ops = &aiu_i2s_dma_ops,
|
||||
+ .pcm_new = aiu_i2s_dma_new,
|
||||
+};
|
||||
+
|
||||
+static int aiu_i2s_dma_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct aiu_i2s_dma *priv;
|
||||
+ int ret;
|
||||
+
|
||||
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
+ if(!priv)
|
||||
+ return -ENOMEM;
|
||||
+ platform_set_drvdata(pdev, priv);
|
||||
+
|
||||
+ ret = aiu_common_register(pdev);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ priv->regmap = syscon_node_to_regmap(dev->parent->of_node);
|
||||
+ if (IS_ERR(priv->regmap)) {
|
||||
+ dev_err(dev, "failed to get our regmap\n");
|
||||
+ return PTR_ERR(priv->regmap);
|
||||
+ }
|
||||
+
|
||||
+ priv->i2s_out = devm_clk_get(dev, "i2s_out");
|
||||
+ if (IS_ERR(priv->i2s_out)) {
|
||||
+ if(PTR_ERR(priv->i2s_out) != -EPROBE_DEFER)
|
||||
+ dev_err(dev, "Can't get i2s_out\n");
|
||||
+ return PTR_ERR(priv->i2s_out);
|
||||
+ }
|
||||
+
|
||||
+ priv->irq = platform_get_irq(pdev, 0);
|
||||
+ if (priv->irq <= 0) {
|
||||
+ dev_err(dev, "Can't get i2s ddr irq\n");
|
||||
+ return priv->irq;
|
||||
+ }
|
||||
+
|
||||
+ return snd_soc_register_platform(dev, &aiu_i2s_platform);
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id aiu_i2s_dma_match[] = {
|
||||
+ { .compatible = "amlogic,meson-aiu-i2s-dma", },
|
||||
+ {}
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, aiu_i2s_dma_match);
|
||||
+
|
||||
+static struct platform_driver aiu_i2s_dma_pdrv = {
|
||||
+ .probe = aiu_i2s_dma_probe,
|
||||
+ .driver = {
|
||||
+ .name = DRV_NAME,
|
||||
+ .of_match_table = aiu_i2s_dma_match,
|
||||
+ },
|
||||
+};
|
||||
+module_platform_driver(aiu_i2s_dma_pdrv);
|
||||
+
|
||||
+MODULE_DESCRIPTION("Meson AIU i2s DMA ASoC Driver");
|
||||
+MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
|
||||
+MODULE_LICENSE("GPL v2");
|
||||
diff --git a/sound/soc/meson/aiu.h b/sound/soc/meson/aiu.h
|
||||
new file mode 100644
|
||||
index 0000000..a9d1c58
|
||||
--- /dev/null
|
||||
+++ b/sound/soc/meson/aiu.h
|
||||
@@ -0,0 +1,6 @@
|
||||
+#ifndef _AIU_H_
|
||||
+#define _AIU_H_
|
||||
+
|
||||
+int aiu_common_register(struct platform_device *pdev);
|
||||
+
|
||||
+#endif /* _AIU_H_ */
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,480 @@
|
|||
From e5e1644671e95c258a854506bf1937a1f5e1dbe1 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Sun, 12 Feb 2017 00:53:08 +0100
|
||||
Subject: [PATCH 77/93] snd: soc: meson: support for aiu i2s dai
|
||||
|
||||
Initial support for meson aiu i2s dai
|
||||
TO BE COMPLETED...
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
---
|
||||
sound/soc/meson/Kconfig | 8 +
|
||||
sound/soc/meson/Makefile | 1 +
|
||||
sound/soc/meson/aiu-i2s-dai.c | 428 ++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 437 insertions(+)
|
||||
create mode 100644 sound/soc/meson/aiu-i2s-dai.c
|
||||
|
||||
diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig
|
||||
index f2504c6..796eff0 100644
|
||||
--- a/sound/soc/meson/Kconfig
|
||||
+++ b/sound/soc/meson/Kconfig
|
||||
@@ -1,6 +1,14 @@
|
||||
menu "Amlogic SoC Audio Support"
|
||||
depends on ARCH_MESON || COMPILE_TEST
|
||||
|
||||
+config SND_MESON_AIU_I2S_DAI
|
||||
+ tristate "Meson I2S Output DAI Support"
|
||||
+ select MFD_SYSCON
|
||||
+ select SND_MESON_AIU_COMMON
|
||||
+ help
|
||||
+ This adds ASoC driver the Amlogic Meson i2s DAI
|
||||
+ If unsure select "N".
|
||||
+
|
||||
config SND_MESON_AIU_I2S_DMA
|
||||
tristate "Meson I2S Output DMA Support"
|
||||
select MFD_SYSCON
|
||||
diff --git a/sound/soc/meson/Makefile b/sound/soc/meson/Makefile
|
||||
index b237894..0fea1c1 100644
|
||||
--- a/sound/soc/meson/Makefile
|
||||
+++ b/sound/soc/meson/Makefile
|
||||
@@ -1,2 +1,3 @@
|
||||
obj-$(CONFIG_SND_MESON_AIU_COMMON) += aiu-common.o
|
||||
+obj-$(CONFIG_SND_MESON_AIU_I2S_DAI) += aiu-i2s-dai.o
|
||||
obj-$(CONFIG_SND_MESON_AIU_I2S_DMA) += aiu-i2s-dma.o
|
||||
diff --git a/sound/soc/meson/aiu-i2s-dai.c b/sound/soc/meson/aiu-i2s-dai.c
|
||||
new file mode 100644
|
||||
index 0000000..6756848
|
||||
--- /dev/null
|
||||
+++ b/sound/soc/meson/aiu-i2s-dai.c
|
||||
@@ -0,0 +1,428 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2017 BayLibre, SAS
|
||||
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
|
||||
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation; either version 2 of the
|
||||
+ * License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful, but
|
||||
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ * General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/mfd/syscon.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/regmap.h>
|
||||
+
|
||||
+#include <sound/pcm_params.h>
|
||||
+#include <sound/soc.h>
|
||||
+#include <sound/soc-dai.h>
|
||||
+
|
||||
+#include "aiu.h"
|
||||
+#include "aiu-regs.h"
|
||||
+
|
||||
+#define DRV_NAME "meson-aiu-i2s-dai"
|
||||
+
|
||||
+struct aiu_i2s_dai {
|
||||
+ struct regmap *regmap;
|
||||
+ struct clk *amclk;
|
||||
+ struct clk *aoclk;
|
||||
+ struct clk *mixer_if;
|
||||
+ bool bclks_idle;
|
||||
+};
|
||||
+
|
||||
+#define AIU_CLK_CTRL_I2S_DIV_EN BIT(0)
|
||||
+#define AIU_CLK_CTRL_I2S_DIV_MASK GENMASK(3, 2)
|
||||
+#define AIU_CLK_CTRL_AOCLK_POLARITY_MASK BIT(6)
|
||||
+#define AIU_CLK_CTRL_AOCLK_POLARITY_NORMAL (0 << 6)
|
||||
+#define AIU_CLK_CTRL_AOCLK_POLARITY_INVERTED (1 << 6)
|
||||
+#define AIU_CLK_CTRL_ALRCLK_POLARITY_MASK BIT(7)
|
||||
+#define AIU_CLK_CTRL_ALRCLK_POLARITY_NORMAL (0 << 7)
|
||||
+#define AIU_CLK_CTRL_ALRCLK_POLARITY_INVERTED (1 << 7)
|
||||
+#define AIU_CLK_CTRL_ALRCLK_SKEW_MASK GENMASK(9, 8)
|
||||
+#define AIU_CLK_CTRL_ALRCLK_LEFT_J (0 << 8)
|
||||
+#define AIU_CLK_CTRL_ALRCLK_I2S (1 << 8)
|
||||
+#define AIU_CLK_CTRL_ALRCLK_RIGHT_J (2 << 8)
|
||||
+#define AIU_CLK_CTRL_MORE_I2S_DIV_MASK GENMASK(5, 0)
|
||||
+#define AIU_CLK_CTRL_MORE_I2S_DIV(div) ((div - 1) << 0)
|
||||
+#define AIU_CODEC_DAC_LRCLK_CTRL_DIV_MASK GENMASK(11, 0)
|
||||
+#define AIU_CODEC_DAC_LRCLK_CTRL_DIV(div) ((div - 1) << 0)
|
||||
+#define AIU_I2S_DAC_CFG_PAYLOAD_SIZE_MASK GENMASK(1, 0)
|
||||
+#define AIU_I2S_DAC_CFG_AOCLK_32 (0 << 0)
|
||||
+#define AIU_I2S_DAC_CFG_AOCLK_48 (2 << 0)
|
||||
+#define AIU_I2S_DAC_CFG_AOCLK_64 (3 << 0)
|
||||
+#define AIU_I2S_MISC_HOLD_EN BIT(2)
|
||||
+#define AIU_I2S_MISC_FORCE_LR BIT(4)
|
||||
+
|
||||
+static void __hold(struct aiu_i2s_dai *priv, bool enable)
|
||||
+{
|
||||
+ regmap_update_bits(priv->regmap, AIU_I2S_MISC,
|
||||
+ AIU_I2S_MISC_HOLD_EN,
|
||||
+ enable ? AIU_I2S_MISC_HOLD_EN : 0);
|
||||
+}
|
||||
+
|
||||
+static void __playback_start(struct aiu_i2s_dai *priv)
|
||||
+{
|
||||
+ regmap_update_bits(priv->regmap, AIU_CLK_CTRL,
|
||||
+ AIU_CLK_CTRL_I2S_DIV_EN,
|
||||
+ AIU_CLK_CTRL_I2S_DIV_EN);
|
||||
+ __hold(priv, false);
|
||||
+}
|
||||
+
|
||||
+static void __playback_stop(struct aiu_i2s_dai *priv, bool clk_force)
|
||||
+{
|
||||
+ __hold(priv, true);
|
||||
+ /* Disable the bit clks if necessary */
|
||||
+ if (clk_force || !priv->bclks_idle)
|
||||
+ regmap_update_bits(priv->regmap, AIU_CLK_CTRL,
|
||||
+ AIU_CLK_CTRL_I2S_DIV_EN,
|
||||
+ 0);
|
||||
+
|
||||
+}
|
||||
+
|
||||
+static int aiu_i2s_dai_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||
+ struct snd_soc_dai *dai)
|
||||
+{
|
||||
+ struct aiu_i2s_dai *priv = snd_soc_dai_get_drvdata(dai);
|
||||
+ bool clk_force_stop = false;
|
||||
+
|
||||
+ switch (cmd) {
|
||||
+ case SNDRV_PCM_TRIGGER_START:
|
||||
+ case SNDRV_PCM_TRIGGER_RESUME:
|
||||
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||
+ __playback_start(priv);
|
||||
+ return 0;
|
||||
+
|
||||
+ case SNDRV_PCM_TRIGGER_STOP:
|
||||
+ case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
+ clk_force_stop = true;
|
||||
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||
+ __playback_stop(priv, clk_force_stop);
|
||||
+ return 0;
|
||||
+
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int __get_lrclk_div(unsigned int os, unsigned int width)
|
||||
+{
|
||||
+ if (((os % 48) == 0) && (width == 24))
|
||||
+ return 48;
|
||||
+ else if (((os % 64) == 0) && (width == 24))
|
||||
+ return 64;
|
||||
+ else if (((os % 32) == 0) && (width == 16))
|
||||
+ return 32;
|
||||
+
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * FIXME: Most of this stuff should be done using CCF when the support of
|
||||
+ * regmap based clocks is added
|
||||
+ */
|
||||
+static int __bclks_set_rate(struct aiu_i2s_dai *priv, unsigned int srate,
|
||||
+ unsigned int width)
|
||||
+{
|
||||
+ int div_lrclk, div_bclk;
|
||||
+ unsigned int os;
|
||||
+ u32 val;
|
||||
+
|
||||
+ /* Get the oversampling factor */
|
||||
+ os = DIV_ROUND_CLOSEST(clk_get_rate(priv->amclk), srate);
|
||||
+
|
||||
+ /* Get the divider between bclk and lrclk */
|
||||
+ div_lrclk = __get_lrclk_div(os, width);
|
||||
+
|
||||
+ switch (div_lrclk) {
|
||||
+ case 32:
|
||||
+ val = AIU_I2S_DAC_CFG_AOCLK_32;
|
||||
+ break;
|
||||
+ case 48:
|
||||
+ val = AIU_I2S_DAC_CFG_AOCLK_48;
|
||||
+ break;
|
||||
+ case 64:
|
||||
+ val = AIU_I2S_DAC_CFG_AOCLK_64;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ /* Set the divider between lrclk and bclk */
|
||||
+ regmap_update_bits(priv->regmap, AIU_I2S_DAC_CFG,
|
||||
+ AIU_I2S_DAC_CFG_PAYLOAD_SIZE_MASK,
|
||||
+ val);
|
||||
+
|
||||
+ regmap_update_bits(priv->regmap, AIU_CODEC_DAC_LRCLK_CTRL,
|
||||
+ AIU_CODEC_DAC_LRCLK_CTRL_DIV_MASK,
|
||||
+ AIU_CODEC_DAC_LRCLK_CTRL_DIV(div_lrclk));
|
||||
+
|
||||
+ /* Set the divider between blclk and amclk */
|
||||
+ div_bclk = os / div_lrclk;
|
||||
+
|
||||
+ /* Use CLK_MORE for the i2s divider */
|
||||
+ regmap_update_bits(priv->regmap, AIU_CLK_CTRL,
|
||||
+ AIU_CLK_CTRL_I2S_DIV_MASK,
|
||||
+ 0);
|
||||
+
|
||||
+ regmap_update_bits(priv->regmap, AIU_CLK_CTRL_MORE,
|
||||
+ AIU_CLK_CTRL_MORE_I2S_DIV_MASK,
|
||||
+ AIU_CLK_CTRL_MORE_I2S_DIV(div_bclk));
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int aiu_i2s_dai_hw_params(struct snd_pcm_substream *substream,
|
||||
+ struct snd_pcm_hw_params *params,
|
||||
+ struct snd_soc_dai *dai)
|
||||
+{
|
||||
+ struct aiu_i2s_dai *priv = snd_soc_dai_get_drvdata(dai);
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = __bclks_set_rate(priv, params_rate(params), params_width(params));
|
||||
+ if (ret) {
|
||||
+ dev_err(dai->dev, "Unable set to the i2s clock rates\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int aiu_i2s_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
||||
+{
|
||||
+ struct aiu_i2s_dai *priv = snd_soc_dai_get_drvdata(dai);
|
||||
+ u32 val;
|
||||
+
|
||||
+ if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* DAI output mode */
|
||||
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
+ case SND_SOC_DAIFMT_I2S:
|
||||
+ val = AIU_CLK_CTRL_ALRCLK_I2S;
|
||||
+ break;
|
||||
+ case SND_SOC_DAIFMT_LEFT_J: /* !TBC! */
|
||||
+ val = AIU_CLK_CTRL_ALRCLK_LEFT_J;
|
||||
+ break;
|
||||
+ case SND_SOC_DAIFMT_RIGHT_J: /* !TBC! */
|
||||
+ val = AIU_CLK_CTRL_ALRCLK_RIGHT_J;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ regmap_update_bits(priv->regmap, AIU_CLK_CTRL,
|
||||
+ AIU_CLK_CTRL_ALRCLK_SKEW_MASK,
|
||||
+ val);
|
||||
+
|
||||
+ /* DAI clock polarity */
|
||||
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
|
||||
+ case SND_SOC_DAIFMT_IB_IF:
|
||||
+ /* Invert both clocks */
|
||||
+ val = AIU_CLK_CTRL_ALRCLK_POLARITY_INVERTED |
|
||||
+ AIU_CLK_CTRL_AOCLK_POLARITY_INVERTED;
|
||||
+ break;
|
||||
+ case SND_SOC_DAIFMT_IB_NF:
|
||||
+ /* Invert bit clock */
|
||||
+ val = AIU_CLK_CTRL_ALRCLK_POLARITY_NORMAL |
|
||||
+ AIU_CLK_CTRL_AOCLK_POLARITY_INVERTED;
|
||||
+ break;
|
||||
+ case SND_SOC_DAIFMT_NB_IF:
|
||||
+ /* Invert frame clock */
|
||||
+ val = AIU_CLK_CTRL_ALRCLK_POLARITY_INVERTED |
|
||||
+ AIU_CLK_CTRL_AOCLK_POLARITY_NORMAL;
|
||||
+ break;
|
||||
+ case SND_SOC_DAIFMT_NB_NF:
|
||||
+ /* Normal clocks */
|
||||
+ val = AIU_CLK_CTRL_ALRCLK_POLARITY_NORMAL |
|
||||
+ AIU_CLK_CTRL_AOCLK_POLARITY_NORMAL;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ regmap_update_bits(priv->regmap, AIU_CLK_CTRL,
|
||||
+ AIU_CLK_CTRL_ALRCLK_POLARITY_MASK |
|
||||
+ AIU_CLK_CTRL_AOCLK_POLARITY_MASK,
|
||||
+ val);
|
||||
+
|
||||
+ switch (fmt & SND_SOC_DAIFMT_CLOCK_MASK) {
|
||||
+ case SND_SOC_DAIFMT_CONT:
|
||||
+ priv->bclks_idle = true;
|
||||
+ break;
|
||||
+ case SND_SOC_DAIFMT_GATED:
|
||||
+ priv->bclks_idle = false;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int aiu_i2s_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
|
||||
+ unsigned int freq, int dir)
|
||||
+{
|
||||
+ struct aiu_i2s_dai *priv = snd_soc_dai_get_drvdata(dai);
|
||||
+ int ret;
|
||||
+
|
||||
+ if (WARN_ON(clk_id != 0))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (dir == SND_SOC_CLOCK_IN)
|
||||
+ return 0;
|
||||
+
|
||||
+ ret = clk_set_rate(priv->amclk, freq);
|
||||
+ if (ret) {
|
||||
+ dev_err(dai->dev, "Failed to set sysclk to %uHz", freq);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ dev_dbg(dai->dev, "sysclk set to %luHz\n", clk_get_rate(priv->amclk));
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int aiu_i2s_dai_startup(struct snd_pcm_substream *substream,
|
||||
+ struct snd_soc_dai *dai)
|
||||
+{
|
||||
+ struct aiu_i2s_dai *priv = snd_soc_dai_get_drvdata(dai);
|
||||
+ int ret;
|
||||
+
|
||||
+ /* Make sure nothing gets out of the DAI yet*/
|
||||
+ __hold(priv, true);
|
||||
+
|
||||
+ /* I2S encoder needs the mixer interface gate */
|
||||
+ ret = clk_prepare_enable(priv->mixer_if);
|
||||
+ if (ret)
|
||||
+ goto err_mixer_if;
|
||||
+
|
||||
+ /* Enable the i2s master clock */
|
||||
+ ret = clk_prepare_enable(priv->amclk);
|
||||
+ if (ret)
|
||||
+ goto err_amclk;
|
||||
+
|
||||
+ /* Enable the bits clock gate */
|
||||
+ ret = clk_prepare_enable(priv->aoclk);
|
||||
+ if (ret)
|
||||
+ goto err_aoclk;
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+err_aoclk:
|
||||
+ clk_disable_unprepare(priv->amclk);
|
||||
+err_amclk:
|
||||
+ clk_disable_unprepare(priv->mixer_if);
|
||||
+err_mixer_if:
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void aiu_i2s_dai_shutdown(struct snd_pcm_substream *substream,
|
||||
+ struct snd_soc_dai *dai)
|
||||
+{
|
||||
+ struct aiu_i2s_dai *priv = snd_soc_dai_get_drvdata(dai);
|
||||
+
|
||||
+ clk_disable_unprepare(priv->aoclk);
|
||||
+ clk_disable_unprepare(priv->amclk);
|
||||
+ clk_disable_unprepare(priv->mixer_if);
|
||||
+}
|
||||
+
|
||||
+static const struct snd_soc_dai_ops aiu_i2s_dai_ops = {
|
||||
+ .startup = aiu_i2s_dai_startup,
|
||||
+ .shutdown = aiu_i2s_dai_shutdown,
|
||||
+ .trigger = aiu_i2s_dai_trigger,
|
||||
+ .hw_params = aiu_i2s_dai_hw_params,
|
||||
+ .set_fmt = aiu_i2s_dai_set_fmt,
|
||||
+ .set_sysclk = aiu_i2s_dai_set_sysclk,
|
||||
+};
|
||||
+
|
||||
+static struct snd_soc_dai_driver aiu_i2s_dai = {
|
||||
+ .playback = {
|
||||
+ .stream_name = "Playback",
|
||||
+ .channels_min = 2,
|
||||
+ .channels_max = 8,
|
||||
+ .rates = SNDRV_PCM_RATE_8000_192000,
|
||||
+ .formats = (SNDRV_PCM_FMTBIT_S16_LE |
|
||||
+ SNDRV_PCM_FMTBIT_S24_LE )
|
||||
+ },
|
||||
+ .ops = &aiu_i2s_dai_ops,
|
||||
+};
|
||||
+
|
||||
+static const struct snd_soc_component_driver aiu_i2s_dai_component = {
|
||||
+ .name = DRV_NAME,
|
||||
+};
|
||||
+
|
||||
+static int aiu_i2s_dai_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct aiu_i2s_dai *priv;
|
||||
+ int ret;
|
||||
+
|
||||
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
+ if(!priv)
|
||||
+ return -ENOMEM;
|
||||
+ platform_set_drvdata(pdev, priv);
|
||||
+
|
||||
+ ret = aiu_common_register(pdev);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ priv->regmap = syscon_node_to_regmap(dev->parent->of_node);
|
||||
+ if (IS_ERR(priv->regmap)) {
|
||||
+ dev_err(dev, "failed to get our regmap\n");
|
||||
+ return PTR_ERR(priv->regmap);
|
||||
+ }
|
||||
+
|
||||
+ priv->mixer_if = devm_clk_get(dev, "mixer_if");
|
||||
+ if (IS_ERR(priv->mixer_if)) {
|
||||
+ if(PTR_ERR(priv->mixer_if) != -EPROBE_DEFER)
|
||||
+ dev_err(dev, "failed to get mixer interface gate\n");
|
||||
+ return PTR_ERR(priv->mixer_if);
|
||||
+ }
|
||||
+
|
||||
+ priv->aoclk = devm_clk_get(dev, "aoclk");
|
||||
+ if (IS_ERR(priv->aoclk)) {
|
||||
+ if(PTR_ERR(priv->aoclk) != -EPROBE_DEFER)
|
||||
+ dev_err(dev, "failed to get bit clocks gate\n");
|
||||
+ return PTR_ERR(priv->aoclk);
|
||||
+ }
|
||||
+
|
||||
+ priv->amclk = devm_clk_get(dev, "amclk");
|
||||
+ if (IS_ERR(priv->amclk)) {
|
||||
+ if(PTR_ERR(priv->amclk) != -EPROBE_DEFER)
|
||||
+ dev_err(dev, "failed to get the i2s master clock\n");
|
||||
+ return PTR_ERR(priv->amclk);
|
||||
+ }
|
||||
+
|
||||
+ return devm_snd_soc_register_component(dev, &aiu_i2s_dai_component,
|
||||
+ &aiu_i2s_dai, 1);
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id aiu_i2s_dai_match[] = {
|
||||
+ { .compatible = "amlogic,meson-aiu-i2s-dai", },
|
||||
+ {}
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, aiu_i2s_dai_match);
|
||||
+
|
||||
+static struct platform_driver aiu_i2s_dai_pdrv = {
|
||||
+ .probe = aiu_i2s_dai_probe,
|
||||
+ .driver = {
|
||||
+ .name = DRV_NAME,
|
||||
+ .of_match_table = aiu_i2s_dai_match,
|
||||
+ },
|
||||
+};
|
||||
+module_platform_driver(aiu_i2s_dai_pdrv);
|
||||
+
|
||||
+MODULE_DESCRIPTION("Meson AIU i2s DAI ASoC Driver");
|
||||
+MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
|
||||
+MODULE_LICENSE("GPL v2");
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
From 564a578e7c4b2bc120ad735058d22a0d1780fc01 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Sun, 12 Feb 2017 00:42:18 +0100
|
||||
Subject: [PATCH 78/93] snd: soc: codec: add es7134lv dac support
|
||||
|
||||
TO BE COMPLETED ...
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
---
|
||||
sound/soc/codecs/Kconfig | 4 ++
|
||||
sound/soc/codecs/Makefile | 2 +
|
||||
sound/soc/codecs/es7134lv.c | 95 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 101 insertions(+)
|
||||
create mode 100644 sound/soc/codecs/es7134lv.c
|
||||
|
||||
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
|
||||
index 9e1718a..dc933b4 100644
|
||||
--- a/sound/soc/codecs/Kconfig
|
||||
+++ b/sound/soc/codecs/Kconfig
|
||||
@@ -72,6 +72,7 @@ config SND_SOC_ALL_CODECS
|
||||
select SND_SOC_DMIC
|
||||
select SND_SOC_ES8328_SPI if SPI_MASTER
|
||||
select SND_SOC_ES8328_I2C if I2C
|
||||
+ select SND_SOC_ES7134LV
|
||||
select SND_SOC_GTM601
|
||||
select SND_SOC_HDAC_HDMI
|
||||
select SND_SOC_ICS43432
|
||||
@@ -535,6 +536,9 @@ config SND_SOC_ES8328_SPI
|
||||
tristate
|
||||
select SND_SOC_ES8328
|
||||
|
||||
+config SND_SOC_ES7134LV
|
||||
+ tristate "Everest ES7134LV CODEC"
|
||||
+
|
||||
config SND_SOC_GTM601
|
||||
tristate 'GTM601 UMTS modem audio codec'
|
||||
|
||||
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
|
||||
index 7e1dad7..a217310 100644
|
||||
--- a/sound/soc/codecs/Makefile
|
||||
+++ b/sound/soc/codecs/Makefile
|
||||
@@ -66,6 +66,7 @@ snd-soc-dmic-objs := dmic.o
|
||||
snd-soc-es8328-objs := es8328.o
|
||||
snd-soc-es8328-i2c-objs := es8328-i2c.o
|
||||
snd-soc-es8328-spi-objs := es8328-spi.o
|
||||
+snd-soc-es7134lv-objs := es7134lv.o
|
||||
snd-soc-gtm601-objs := gtm601.o
|
||||
snd-soc-hdac-hdmi-objs := hdac_hdmi.o
|
||||
snd-soc-ics43432-objs := ics43432.o
|
||||
@@ -295,6 +296,7 @@ obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o
|
||||
obj-$(CONFIG_SND_SOC_ES8328) += snd-soc-es8328.o
|
||||
obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o
|
||||
obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o
|
||||
+obj-$(CONFIG_SND_SOC_ES7134LV) += snd-soc-es7134lv.o
|
||||
obj-$(CONFIG_SND_SOC_GTM601) += snd-soc-gtm601.o
|
||||
obj-$(CONFIG_SND_SOC_HDAC_HDMI) += snd-soc-hdac-hdmi.o
|
||||
obj-$(CONFIG_SND_SOC_ICS43432) += snd-soc-ics43432.o
|
||||
diff --git a/sound/soc/codecs/es7134lv.c b/sound/soc/codecs/es7134lv.c
|
||||
new file mode 100644
|
||||
index 0000000..a24d555
|
||||
--- /dev/null
|
||||
+++ b/sound/soc/codecs/es7134lv.c
|
||||
@@ -0,0 +1,95 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2017 BayLibre, SAS.
|
||||
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of version 2 of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful, but
|
||||
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ * General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
+ * The full GNU General Public License is included in this distribution
|
||||
+ * in the file called COPYING.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/module.h>
|
||||
+#include <sound/soc.h>
|
||||
+
|
||||
+/*
|
||||
+ * The everest 7134lv is a very simple DA converter with no register
|
||||
+ */
|
||||
+
|
||||
+static const struct snd_soc_dapm_widget es7134lv_dapm_widgets[] = {
|
||||
+ SND_SOC_DAPM_OUTPUT("AOUTL"),
|
||||
+ SND_SOC_DAPM_OUTPUT("AOUTR"),
|
||||
+};
|
||||
+
|
||||
+static const struct snd_soc_dapm_route es7134lv_dapm_routes[] = {
|
||||
+ { "AOUTL", NULL, "Playback" },
|
||||
+ { "AOUTR", NULL, "Playback" },
|
||||
+};
|
||||
+
|
||||
+static struct snd_soc_dai_driver es7134lv_dai = {
|
||||
+ .name = "es7134lv-hifi",
|
||||
+ .playback = {
|
||||
+ .stream_name = "Playback",
|
||||
+ .channels_min = 2,
|
||||
+ .channels_max = 2,
|
||||
+ .rates = SNDRV_PCM_RATE_8000_192000,
|
||||
+ .formats = (SNDRV_PCM_FMTBIT_S16_LE |
|
||||
+ SNDRV_PCM_FMTBIT_S18_3LE |
|
||||
+ SNDRV_PCM_FMTBIT_S20_3LE |
|
||||
+ SNDRV_PCM_FMTBIT_S24_3LE |
|
||||
+ SNDRV_PCM_FMTBIT_S24_LE),
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct snd_soc_codec_driver es7134lv_codec_driver = {
|
||||
+ .component_driver = {
|
||||
+ .dapm_widgets = es7134lv_dapm_widgets,
|
||||
+ .num_dapm_widgets = ARRAY_SIZE(es7134lv_dapm_widgets),
|
||||
+ .dapm_routes = es7134lv_dapm_routes,
|
||||
+ .num_dapm_routes = ARRAY_SIZE(es7134lv_dapm_routes),
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static int es7134lv_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ return snd_soc_register_codec(&pdev->dev,
|
||||
+ &es7134lv_codec_driver,
|
||||
+ &es7134lv_dai, 1);
|
||||
+}
|
||||
+
|
||||
+static int es7134lv_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ snd_soc_unregister_codec(&pdev->dev);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_OF
|
||||
+static const struct of_device_id es7134lv_ids[] = {
|
||||
+ { .compatible = "everest,es7134lv", },
|
||||
+ { }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, es7134lv_ids);
|
||||
+#endif
|
||||
+
|
||||
+static struct platform_driver es7134lv_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "es7134lv",
|
||||
+ .of_match_table = of_match_ptr(es7134lv_ids),
|
||||
+ },
|
||||
+ .probe = es7134lv_probe,
|
||||
+ .remove = es7134lv_remove,
|
||||
+};
|
||||
+
|
||||
+module_platform_driver(es7134lv_driver);
|
||||
+
|
||||
+MODULE_DESCRIPTION("ASoC ES7134LV audio codec driver");
|
||||
+MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
|
||||
+MODULE_LICENSE("GPL");
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
From abb052acd69dfbe05ae9e03d14f6fbed4a3a96c0 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Thu, 26 Jan 2017 11:11:25 +0100
|
||||
Subject: [PATCH 79/93] dt-bindings: clk: gxbb: expose MPLL0 and MPLL1 clocks
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
---
|
||||
drivers/clk/meson/gxbb.h | 4 ++--
|
||||
include/dt-bindings/clock/gxbb-clkc.h | 2 ++
|
||||
2 files changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h
|
||||
index 298bfa5..084b016 100644
|
||||
--- a/drivers/clk/meson/gxbb.h
|
||||
+++ b/drivers/clk/meson/gxbb.h
|
||||
@@ -181,8 +181,8 @@
|
||||
#define CLKID_MPEG_SEL 10
|
||||
#define CLKID_MPEG_DIV 11
|
||||
/* CLKID_CLK81 */
|
||||
-#define CLKID_MPLL0 13
|
||||
-#define CLKID_MPLL1 14
|
||||
+/* CLKID_MPLL0 */
|
||||
+/* CLKID_MPLL1 */
|
||||
/* CLKID_MPLL2 */
|
||||
#define CLKID_DDR 16
|
||||
#define CLKID_DOS 17
|
||||
diff --git a/include/dt-bindings/clock/gxbb-clkc.h b/include/dt-bindings/clock/gxbb-clkc.h
|
||||
index cfd7558..a1246d2 100644
|
||||
--- a/include/dt-bindings/clock/gxbb-clkc.h
|
||||
+++ b/include/dt-bindings/clock/gxbb-clkc.h
|
||||
@@ -12,6 +12,8 @@
|
||||
#define CLKID_FCLK_DIV4 6
|
||||
#define CLKID_GP0_PLL 9
|
||||
#define CLKID_CLK81 12
|
||||
+#define CLKID_MPLL0 13
|
||||
+#define CLKID_MPLL1 14
|
||||
#define CLKID_MPLL2 15
|
||||
#define CLKID_SPI 34
|
||||
#define CLKID_I2C 22
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
From f6986222eefd41918451f33b92d0bfe21174e636 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Thu, 26 Jan 2017 11:12:52 +0100
|
||||
Subject: [PATCH 80/93] dt-bindings: clock: gxbb: expose i2s master clock
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
|
||||
Conflicts:
|
||||
include/dt-bindings/clock/gxbb-clkc.h
|
||||
---
|
||||
drivers/clk/meson/gxbb.h | 4 ++--
|
||||
include/dt-bindings/clock/gxbb-clkc.h | 8 +++++---
|
||||
2 files changed, 7 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h
|
||||
index 084b016..740b755f 100644
|
||||
--- a/drivers/clk/meson/gxbb.h
|
||||
+++ b/drivers/clk/meson/gxbb.h
|
||||
@@ -266,8 +266,8 @@
|
||||
/* CLKID_SD_EMMC_B */
|
||||
/* CLKID_SD_EMMC_C */
|
||||
#define CLKID_MPLL0_PLL 97
|
||||
-#define CLKID_CTS_AMCLK 98
|
||||
-#define CLKID_CTS_AMCLK_SEL 99
|
||||
+/* CLKID_CTS_AMCLK */
|
||||
+/* CLKID_CTS_AMCLK_SEL */
|
||||
#define CLKID_CTS_AMCLK_DIV 100
|
||||
/* CLKID_MALI_0 */
|
||||
/* CLKID_MALI_1 */
|
||||
diff --git a/include/dt-bindings/clock/gxbb-clkc.h b/include/dt-bindings/clock/gxbb-clkc.h
|
||||
index a1246d2..0e690ac 100644
|
||||
--- a/include/dt-bindings/clock/gxbb-clkc.h
|
||||
+++ b/include/dt-bindings/clock/gxbb-clkc.h
|
||||
@@ -29,8 +29,10 @@
|
||||
#define CLKID_SD_EMMC_A 94
|
||||
#define CLKID_SD_EMMC_B 95
|
||||
#define CLKID_SD_EMMC_C 96
|
||||
-#define CLKID_MALI_0 97
|
||||
-#define CLKID_MALI_1 98
|
||||
-#define CLKID_MALI 99
|
||||
+#define CLKID_CTS_AMCLK 98
|
||||
+#define CLKID_CTS_AMCLK_SEL 99
|
||||
+#define CLKID_MALI_0 101
|
||||
+#define CLKID_MALI_1 102
|
||||
+#define CLKID_MALI 103
|
||||
|
||||
#endif /* __GXBB_CLKC_H */
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
From 2878ea522ede6a743148419877ef28b3387369a3 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Sun, 12 Feb 2017 00:58:59 +0100
|
||||
Subject: [PATCH 81/93] dt-bindings: expose i2s dma and dai clock gates
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
---
|
||||
drivers/clk/meson/gxbb.h | 10 +++++-----
|
||||
include/dt-bindings/clock/gxbb-clkc.h | 5 +++++
|
||||
2 files changed, 10 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h
|
||||
index 740b755f..2c66d88 100644
|
||||
--- a/drivers/clk/meson/gxbb.h
|
||||
+++ b/drivers/clk/meson/gxbb.h
|
||||
@@ -206,16 +206,16 @@
|
||||
#define CLKID_I2S_SPDIF 35
|
||||
#define CLKID_ETH 36
|
||||
#define CLKID_DEMUX 37
|
||||
-#define CLKID_AIU_GLUE 38
|
||||
+/* CLKID_AIU_GLUE */
|
||||
#define CLKID_IEC958 39
|
||||
-#define CLKID_I2S_OUT 40
|
||||
+/* CLKID_I2S_OUT */
|
||||
#define CLKID_AMCLK 41
|
||||
#define CLKID_AIFIFO2 42
|
||||
#define CLKID_MIXER 43
|
||||
-#define CLKID_MIXER_IFACE 44
|
||||
+/* CLKID_MIXER_IFACE */
|
||||
#define CLKID_ADC 45
|
||||
#define CLKID_BLKMV 46
|
||||
-#define CLKID_AIU 47
|
||||
+/* CLKID_AIU */
|
||||
#define CLKID_UART1 48
|
||||
#define CLKID_G2D 49
|
||||
/* CLKID_USB0 */
|
||||
@@ -248,7 +248,7 @@
|
||||
/* CLKID_GCLK_VENCI_INT0 */
|
||||
#define CLKID_GCLK_VENCI_INT 78
|
||||
#define CLKID_DAC_CLK 79
|
||||
-#define CLKID_AOCLK_GATE 80
|
||||
+/* CLKID_AOCLK_GATE */
|
||||
#define CLKID_IEC958_GATE 81
|
||||
#define CLKID_ENC480P 82
|
||||
#define CLKID_RNG1 83
|
||||
diff --git a/include/dt-bindings/clock/gxbb-clkc.h b/include/dt-bindings/clock/gxbb-clkc.h
|
||||
index 0e690ac..ce5e0da 100644
|
||||
--- a/include/dt-bindings/clock/gxbb-clkc.h
|
||||
+++ b/include/dt-bindings/clock/gxbb-clkc.h
|
||||
@@ -18,6 +18,10 @@
|
||||
#define CLKID_SPI 34
|
||||
#define CLKID_I2C 22
|
||||
#define CLKID_ETH 36
|
||||
+#define CLKID_AIU_GLUE 38
|
||||
+#define CLKID_I2S_OUT 40
|
||||
+#define CLKID_MIXER_IFACE 44
|
||||
+#define CLKID_AIU 47
|
||||
#define CLKID_USB0 50
|
||||
#define CLKID_USB1 51
|
||||
#define CLKID_USB 55
|
||||
@@ -25,6 +29,7 @@
|
||||
#define CLKID_USB1_DDR_BRIDGE 64
|
||||
#define CLKID_USB0_DDR_BRIDGE 65
|
||||
#define CLKID_GCLK_VENCI_INT0 77
|
||||
+#define CLKID_AOCLK_GATE 80
|
||||
#define CLKID_AO_I2C 93
|
||||
#define CLKID_SD_EMMC_A 94
|
||||
#define CLKID_SD_EMMC_B 95
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
From 045b11333a76b8e94c37665cea6b94a2b562a666 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Sun, 12 Feb 2017 01:00:13 +0100
|
||||
Subject: [PATCH 82/93] ARM64: dts: meson: initial aiu support for gxbb
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
---
|
||||
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 31 +++++++++++++++++++++++++++++
|
||||
1 file changed, 31 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
index ea111a2..6346776 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
@@ -163,6 +163,37 @@
|
||||
clocks = <&clkc CLKID_SPI>;
|
||||
status = "disabled";
|
||||
};
|
||||
+
|
||||
+ aiu: aiu@5400 {
|
||||
+ compatible = "amlogic,meson-aiu" , "simple-mfd", "syscon" ;
|
||||
+ reg = <0x0 0x5400 0x0 0x24c>;
|
||||
+
|
||||
+ aiu_i2s_dai: aiu-i2s-dai {
|
||||
+ #sound-dai-cells = <0>;
|
||||
+ compatible = "amlogic,meson-aiu-i2s-dai";
|
||||
+ clocks = <&clkc CLKID_CTS_AMCLK>,
|
||||
+ <&clkc CLKID_AIU>,
|
||||
+ <&clkc CLKID_AIU_GLUE>,
|
||||
+ <&clkc CLKID_AOCLK_GATE>,
|
||||
+ <&clkc CLKID_MIXER_IFACE>;
|
||||
+ clock-names = "amclk","aiu_top", "aiu_glue",
|
||||
+ "aoclk", "mixer_if";
|
||||
+ status = "disbaled";
|
||||
+ };
|
||||
+
|
||||
+ aiu_i2s_dma: aiu_i2s_dma {
|
||||
+ #sound-dai-cells = <0>;
|
||||
+ compatible = "amlogic,meson-aiu-i2s-dma";
|
||||
+ interrupts = <GIC_SPI 48 IRQ_TYPE_EDGE_RISING>;
|
||||
+ clocks = <&clkc CLKID_AIU>,
|
||||
+ <&clkc CLKID_AIU_GLUE>,
|
||||
+ <&clkc CLKID_I2S_OUT>;
|
||||
+ clock-names = "aiu_top", "aiu_glue",
|
||||
+ "i2s_out";
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
};
|
||||
|
||||
ðmac {
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
From 33217241684bbf4017095204ed2e3246cd5aa495 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Sun, 12 Feb 2017 01:01:25 +0100
|
||||
Subject: [PATCH 83/93] ARM64: dts: meson: gxbb-p200: initial sound card
|
||||
support
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
---
|
||||
arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts | 45 +++++++++++++++++++++++++
|
||||
1 file changed, 45 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts
|
||||
index 03e3d76..df820b6 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts
|
||||
@@ -49,6 +49,39 @@
|
||||
/ {
|
||||
compatible = "amlogic,p200", "amlogic,meson-gxbb";
|
||||
model = "Amlogic Meson GXBB P200 Development Board";
|
||||
+
|
||||
+ soc {
|
||||
+ i2s_codec: external-codec {
|
||||
+ #sound-dai-cells = <0>;
|
||||
+ compatible = "everest,es7134lv";
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ sound {
|
||||
+ compatible = "simple-audio-card";
|
||||
+ simple-audio-card,name = "meson-gxbb";
|
||||
+ status = "okay";
|
||||
+
|
||||
+ simple-audio-card,dai-link@0 {
|
||||
+ /* RCA Output */
|
||||
+ format = "i2s";
|
||||
+ mclk-fs = <256>;
|
||||
+ bitclock-master = <&aiu_i2s_dai>;
|
||||
+ frame-master = <&aiu_i2s_dai>;
|
||||
+ plat {
|
||||
+ sound-dai = <&aiu_i2s_dma>;
|
||||
+ };
|
||||
+
|
||||
+ cpu {
|
||||
+ sound-dai = <&aiu_i2s_dai>;
|
||||
+ };
|
||||
+
|
||||
+ codec {
|
||||
+ sound-dai = <&i2s_codec>;
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
};
|
||||
|
||||
&i2c_B {
|
||||
@@ -56,3 +89,15 @@
|
||||
pinctrl-0 = <&i2c_b_pins>;
|
||||
pinctrl-names = "default";
|
||||
};
|
||||
+
|
||||
+&aiu_i2s_dai {
|
||||
+ pinctrl-0 = <&i2s_am_clk_pins>, <&i2s_out_bclks_pins>,
|
||||
+ <&i2s_out_ch01_ao_pins>;
|
||||
+ pinctrl-names = "default";
|
||||
+ status = "okay";
|
||||
+};
|
||||
+
|
||||
+&aiu_i2s_dma {
|
||||
+ status = "okay";
|
||||
+};
|
||||
+
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
From 613430ff3230d0aef2ea415c4b526f3c9521e492 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Tue, 14 Feb 2017 19:09:24 +0100
|
||||
Subject: [PATCH 84/93] snd: meson: add hdmi control bits
|
||||
|
||||
NOT READY FOR ML
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
---
|
||||
sound/soc/meson/aiu-i2s-dai.c | 11 +++++++++++
|
||||
1 file changed, 11 insertions(+)
|
||||
|
||||
diff --git a/sound/soc/meson/aiu-i2s-dai.c b/sound/soc/meson/aiu-i2s-dai.c
|
||||
index 6756848..1f9f3bf 100644
|
||||
--- a/sound/soc/meson/aiu-i2s-dai.c
|
||||
+++ b/sound/soc/meson/aiu-i2s-dai.c
|
||||
@@ -55,8 +55,19 @@ struct aiu_i2s_dai {
|
||||
#define AIU_CLK_CTRL_ALRCLK_RIGHT_J (2 << 8)
|
||||
#define AIU_CLK_CTRL_MORE_I2S_DIV_MASK GENMASK(5, 0)
|
||||
#define AIU_CLK_CTRL_MORE_I2S_DIV(div) ((div - 1) << 0)
|
||||
+#define AIU_CLK_CTRL_MORE_HDMI_TX_SEL_MASK BIT(6)
|
||||
+#define AIU_CLK_CTRL_MORE_HDMI_TX_I958_CLK (0 << 6)
|
||||
+#define AIU_CLK_CTRL_MORE_HDMI_TX_INT_CLK (1 << 6)
|
||||
#define AIU_CODEC_DAC_LRCLK_CTRL_DIV_MASK GENMASK(11, 0)
|
||||
#define AIU_CODEC_DAC_LRCLK_CTRL_DIV(div) ((div - 1) << 0)
|
||||
+#define AIU_HDMI_CLK_DATA_CTRL_CLK_SEL_MASK GENMASK(1, 0)
|
||||
+#define AIU_HDMI_CLK_DATA_CTRL_CLK_DISABLE (0 << 0)
|
||||
+#define AIU_HDMI_CLK_DATA_CTRL_CLK_PCM (1 << 0)
|
||||
+#define AIU_HDMI_CLK_DATA_CTRL_CLK_I2S (2 << 0)
|
||||
+#define AIU_HDMI_CLK_DATA_CTRL_DATA_SEL_MASK GENMASK(5, 4)
|
||||
+#define AIU_HDMI_CLK_DATA_CTRL_DATA_MUTE (0 << 4)
|
||||
+#define AIU_HDMI_CLK_DATA_CTRL_DATA_PCM (1 << 4)
|
||||
+#define AIU_HDMI_CLK_DATA_CTRL_DATA_I2S (2 << 4)
|
||||
#define AIU_I2S_DAC_CFG_PAYLOAD_SIZE_MASK GENMASK(1, 0)
|
||||
#define AIU_I2S_DAC_CFG_AOCLK_32 (0 << 0)
|
||||
#define AIU_I2S_DAC_CFG_AOCLK_48 (2 << 0)
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
From d4fcb333d0d36c0d485ede17ac989b8296a0a88b Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Tue, 14 Feb 2017 19:10:32 +0100
|
||||
Subject: [PATCH 85/93] snd: meson: quick and dirty hdmi activation
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
---
|
||||
sound/soc/meson/aiu-i2s-dai.c | 11 +++++++++++
|
||||
1 file changed, 11 insertions(+)
|
||||
|
||||
diff --git a/sound/soc/meson/aiu-i2s-dai.c b/sound/soc/meson/aiu-i2s-dai.c
|
||||
index 1f9f3bf..56a5b87 100644
|
||||
--- a/sound/soc/meson/aiu-i2s-dai.c
|
||||
+++ b/sound/soc/meson/aiu-i2s-dai.c
|
||||
@@ -206,6 +206,17 @@ static int aiu_i2s_dai_hw_params(struct snd_pcm_substream *substream,
|
||||
return ret;
|
||||
}
|
||||
|
||||
+ /* Quick and dirty hack for HDMI */
|
||||
+ regmap_update_bits(priv->regmap, AIU_HDMI_CLK_DATA_CTRL,
|
||||
+ AIU_HDMI_CLK_DATA_CTRL_CLK_SEL_MASK |
|
||||
+ AIU_HDMI_CLK_DATA_CTRL_DATA_SEL_MASK,
|
||||
+ AIU_HDMI_CLK_DATA_CTRL_CLK_I2S |
|
||||
+ AIU_HDMI_CLK_DATA_CTRL_DATA_I2S);
|
||||
+
|
||||
+ regmap_update_bits(priv->regmap, AIU_CLK_CTRL_MORE,
|
||||
+ AIU_CLK_CTRL_MORE_HDMI_TX_SEL_MASK,
|
||||
+ AIU_CLK_CTRL_MORE_HDMI_TX_INT_CLK);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
From 566355ff11f673633d08d0826fd58e9201a7af70 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Tue, 14 Feb 2017 19:13:04 +0100
|
||||
Subject: [PATCH 86/93] snd: meson: quick and dirty activation of dw-hdmi codec
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
---
|
||||
arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts
|
||||
index df820b6..ceacc36 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts
|
||||
@@ -77,7 +77,8 @@
|
||||
};
|
||||
|
||||
codec {
|
||||
- sound-dai = <&i2s_codec>;
|
||||
+ //sound-dai = <&i2s_codec>;
|
||||
+ sound-dai = <&hdmi_tx>;
|
||||
};
|
||||
};
|
||||
};
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
From 4e8266aaf755068ca04998a19ebe3c00c2608f57 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Tue, 14 Feb 2017 19:12:29 +0100
|
||||
Subject: [PATCH 87/93] ARM64: dts: meson: add sound-dai-cells
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
---
|
||||
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
index 6346776..676c353 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
@@ -662,4 +662,5 @@
|
||||
<&clkc CLKID_CLK81>,
|
||||
<&clkc CLKID_GCLK_VENCI_INT0>;
|
||||
clock-names = "isfr", "iahb", "venci";
|
||||
+ #sound-dai-cells = <0>;
|
||||
};
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
From d3527920b1ab4959557bda86974b143228746ce9 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Tue, 14 Feb 2017 19:18:04 +0100
|
||||
Subject: [PATCH 88/93] drm/meson: select dw-hdmi i2s audio for meson hdmi
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
---
|
||||
drivers/gpu/drm/meson/Kconfig | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/drivers/gpu/drm/meson/Kconfig b/drivers/gpu/drm/meson/Kconfig
|
||||
index 3ce51d8..02d400b 100644
|
||||
--- a/drivers/gpu/drm/meson/Kconfig
|
||||
+++ b/drivers/gpu/drm/meson/Kconfig
|
||||
@@ -13,3 +13,4 @@ config DRM_MESON_DW_HDMI
|
||||
depends on DRM_MESON
|
||||
default y if DRM_MESON
|
||||
select DRM_DW_HDMI
|
||||
+ select DRM_DW_HDMI_I2S_AUDIO
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
From 8099f5de27ff1e58827afdba160121f637a035c7 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Tue, 14 Feb 2017 19:22:33 +0100
|
||||
Subject: [PATCH 89/93] ARM64: config: add meson aiu to defconfig
|
||||
|
||||
NOT READY FOR ML
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
---
|
||||
arch/arm64/configs/defconfig | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
|
||||
index 33b744d..7497bdf 100644
|
||||
--- a/arch/arm64/configs/defconfig
|
||||
+++ b/arch/arm64/configs/defconfig
|
||||
@@ -344,6 +344,8 @@ CONFIG_SOUND=y
|
||||
CONFIG_SND=y
|
||||
CONFIG_SND_SOC=y
|
||||
CONFIG_SND_BCM2835_SOC_I2S=m
|
||||
+CONFIG_SND_MESON_AIU_I2S_DAI=m
|
||||
+CONFIG_SND_MESON_AIU_I2S_DMA=m
|
||||
CONFIG_SND_SOC_RCAR=y
|
||||
CONFIG_SND_SOC_SAMSUNG=y
|
||||
CONFIG_SND_SOC_AK4613=y
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
From 94e399f63f0a7bd2b6fce0e50f032fe68636f6d1 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Tue, 14 Feb 2017 19:29:38 +0100
|
||||
Subject: [PATCH 90/93] ARM64: dts: meson: move sound card from p200 to gxbb
|
||||
|
||||
NOT READY FOR ML
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
---
|
||||
arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts | 45 -------------------------
|
||||
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 30 +++++++++++++++--
|
||||
2 files changed, 28 insertions(+), 47 deletions(-)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts
|
||||
index ceacc36..5f4cd7b 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts
|
||||
@@ -49,40 +49,6 @@
|
||||
/ {
|
||||
compatible = "amlogic,p200", "amlogic,meson-gxbb";
|
||||
model = "Amlogic Meson GXBB P200 Development Board";
|
||||
-
|
||||
- soc {
|
||||
- i2s_codec: external-codec {
|
||||
- #sound-dai-cells = <0>;
|
||||
- compatible = "everest,es7134lv";
|
||||
- status = "okay";
|
||||
- };
|
||||
-
|
||||
- sound {
|
||||
- compatible = "simple-audio-card";
|
||||
- simple-audio-card,name = "meson-gxbb";
|
||||
- status = "okay";
|
||||
-
|
||||
- simple-audio-card,dai-link@0 {
|
||||
- /* RCA Output */
|
||||
- format = "i2s";
|
||||
- mclk-fs = <256>;
|
||||
- bitclock-master = <&aiu_i2s_dai>;
|
||||
- frame-master = <&aiu_i2s_dai>;
|
||||
- plat {
|
||||
- sound-dai = <&aiu_i2s_dma>;
|
||||
- };
|
||||
-
|
||||
- cpu {
|
||||
- sound-dai = <&aiu_i2s_dai>;
|
||||
- };
|
||||
-
|
||||
- codec {
|
||||
- //sound-dai = <&i2s_codec>;
|
||||
- sound-dai = <&hdmi_tx>;
|
||||
- };
|
||||
- };
|
||||
- };
|
||||
- };
|
||||
};
|
||||
|
||||
&i2c_B {
|
||||
@@ -91,14 +57,3 @@
|
||||
pinctrl-names = "default";
|
||||
};
|
||||
|
||||
-&aiu_i2s_dai {
|
||||
- pinctrl-0 = <&i2s_am_clk_pins>, <&i2s_out_bclks_pins>,
|
||||
- <&i2s_out_ch01_ao_pins>;
|
||||
- pinctrl-names = "default";
|
||||
- status = "okay";
|
||||
-};
|
||||
-
|
||||
-&aiu_i2s_dma {
|
||||
- status = "okay";
|
||||
-};
|
||||
-
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
index 676c353..79bc445 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
@@ -135,6 +135,32 @@
|
||||
dr_mode = "host";
|
||||
status = "disabled";
|
||||
};
|
||||
+
|
||||
+ sound {
|
||||
+ compatible = "simple-audio-card";
|
||||
+ simple-audio-card,name = "meson-gxbb";
|
||||
+ status = "okay";
|
||||
+
|
||||
+ simple-audio-card,dai-link@0 {
|
||||
+ /* HDMI Output */
|
||||
+ format = "i2s";
|
||||
+ mclk-fs = <256>;
|
||||
+ bitclock-master = <&aiu_i2s_dai>;
|
||||
+ frame-master = <&aiu_i2s_dai>;
|
||||
+ plat {
|
||||
+ sound-dai = <&aiu_i2s_dma>;
|
||||
+ };
|
||||
+
|
||||
+ cpu {
|
||||
+ sound-dai = <&aiu_i2s_dai>;
|
||||
+ };
|
||||
+
|
||||
+ codec {
|
||||
+ sound-dai = <&hdmi_tx>;
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
};
|
||||
};
|
||||
|
||||
@@ -178,7 +204,7 @@
|
||||
<&clkc CLKID_MIXER_IFACE>;
|
||||
clock-names = "amclk","aiu_top", "aiu_glue",
|
||||
"aoclk", "mixer_if";
|
||||
- status = "disbaled";
|
||||
+ status = "okay";
|
||||
};
|
||||
|
||||
aiu_i2s_dma: aiu_i2s_dma {
|
||||
@@ -190,7 +216,7 @@
|
||||
<&clkc CLKID_I2S_OUT>;
|
||||
clock-names = "aiu_top", "aiu_glue",
|
||||
"i2s_out";
|
||||
- status = "disabled";
|
||||
+ status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
--
|
||||
1.9.1
|
||||
|
34
patch/kernel/odroidc2-next/0091-clk-meson-merge-fixup.patch
Normal file
34
patch/kernel/odroidc2-next/0091-clk-meson-merge-fixup.patch
Normal file
|
@ -0,0 +1,34 @@
|
|||
From 56f7ef263740cf489aaf19d3a395bf0627c58bf7 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Wed, 15 Feb 2017 13:13:52 +0100
|
||||
Subject: [PATCH 91/93] clk: meson: merge fixup
|
||||
|
||||
---
|
||||
drivers/clk/meson/gxbb.c | 4 ----
|
||||
1 file changed, 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
|
||||
index 9e2e407..bac0622 100644
|
||||
--- a/drivers/clk/meson/gxbb.c
|
||||
+++ b/drivers/clk/meson/gxbb.c
|
||||
@@ -1054,8 +1054,6 @@
|
||||
&gxbb_mali_0_sel,
|
||||
&gxbb_mali_1_sel,
|
||||
&gxbb_mali,
|
||||
- &gxbb_mpeg_clk_sel,
|
||||
- &gxbb_sar_adc_clk_sel,
|
||||
&gxbb_cts_amclk_sel,
|
||||
};
|
||||
|
||||
@@ -1063,8 +1061,6 @@
|
||||
&gxbb_mpeg_clk_div,
|
||||
&gxbb_mali_0_div,
|
||||
&gxbb_mali_1_div,
|
||||
- &gxbb_mpeg_clk_div,
|
||||
- &gxbb_sar_adc_clk_div,
|
||||
};
|
||||
|
||||
struct gxbb_composite_clk {
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
From 4dc44c40b6a55b15c2ce5189ce6b9d328b8b4344 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Mon, 27 Mar 2017 11:08:24 +0200
|
||||
Subject: [PATCH 92/93] drm: bridge: dw-hdmi: Use AUTO CTS setup mode when
|
||||
non-AHB audio
|
||||
|
||||
---
|
||||
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 43 +++++++++++++++++++------------
|
||||
1 file changed, 27 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
index 910d579..ad8d62a 100644
|
||||
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
@@ -420,8 +420,12 @@ static void hdmi_set_cts_n(struct dw_hdmi *hdmi, unsigned int cts,
|
||||
/* nshift factor = 0 */
|
||||
hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3);
|
||||
|
||||
- hdmi_writeb(hdmi, ((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) |
|
||||
- HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
|
||||
+ /* Use Auto CTS mode with CTS is unknown */
|
||||
+ if (cts)
|
||||
+ hdmi_writeb(hdmi, ((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) |
|
||||
+ HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
|
||||
+ else
|
||||
+ hdmi_writeb(hdmi, 0, HDMI_AUD_CTS3);
|
||||
hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2);
|
||||
hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1);
|
||||
|
||||
@@ -491,24 +495,31 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
|
||||
{
|
||||
unsigned long ftdms = pixel_clk;
|
||||
unsigned int n, cts;
|
||||
+ u8 config3;
|
||||
u64 tmp;
|
||||
|
||||
n = hdmi_compute_n(sample_rate, pixel_clk);
|
||||
|
||||
- /*
|
||||
- * Compute the CTS value from the N value. Note that CTS and N
|
||||
- * can be up to 20 bits in total, so we need 64-bit math. Also
|
||||
- * note that our TDMS clock is not fully accurate; it is accurate
|
||||
- * to kHz. This can introduce an unnecessary remainder in the
|
||||
- * calculation below, so we don't try to warn about that.
|
||||
- */
|
||||
- tmp = (u64)ftdms * n;
|
||||
- do_div(tmp, 128 * sample_rate);
|
||||
- cts = tmp;
|
||||
-
|
||||
- dev_dbg(hdmi->dev, "%s: fs=%uHz ftdms=%lu.%03luMHz N=%d cts=%d\n",
|
||||
- __func__, sample_rate, ftdms / 1000000, (ftdms / 1000) % 1000,
|
||||
- n, cts);
|
||||
+ config3 = hdmi_readb(hdmi, HDMI_CONFIG3_ID);
|
||||
+
|
||||
+ if (config3 & HDMI_CONFIG3_AHBAUDDMA) {
|
||||
+ /*
|
||||
+ * Compute the CTS value from the N value. Note that CTS and N
|
||||
+ * can be up to 20 bits in total, so we need 64-bit math. Also
|
||||
+ * note that our TDMS clock is not fully accurate; it is
|
||||
+ * accurate to kHz. This can introduce an unnecessary remainder
|
||||
+ * in the calculation below, so we don't try to warn about that.
|
||||
+ */
|
||||
+ tmp = (u64)ftdms * n;
|
||||
+ do_div(tmp, 128 * sample_rate);
|
||||
+ cts = tmp;
|
||||
+
|
||||
+ dev_dbg(hdmi->dev, "%s: fs=%uHz ftdms=%lu.%03luMHz N=%d cts=%d\n",
|
||||
+ __func__, sample_rate,
|
||||
+ ftdms / 1000000, (ftdms / 1000) % 1000,
|
||||
+ n, cts);
|
||||
+ } else
|
||||
+ cts = 0;
|
||||
|
||||
spin_lock_irq(&hdmi->audio_lock);
|
||||
hdmi->audio_n = n;
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
From 6f6cf1c907049feee431c036cbdd3ac475535bd0 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Mon, 27 Mar 2017 12:04:00 +0200
|
||||
Subject: [PATCH 93/93] snd: soc: meson-aiu-i2s: Keep div_lrclk to 64 only
|
||||
|
||||
---
|
||||
sound/soc/meson/aiu-i2s-dai.c | 37 ++++---------------------------------
|
||||
1 file changed, 4 insertions(+), 33 deletions(-)
|
||||
|
||||
diff --git a/sound/soc/meson/aiu-i2s-dai.c b/sound/soc/meson/aiu-i2s-dai.c
|
||||
index 56a5b87..a37758f 100644
|
||||
--- a/sound/soc/meson/aiu-i2s-dai.c
|
||||
+++ b/sound/soc/meson/aiu-i2s-dai.c
|
||||
@@ -126,18 +126,6 @@ static int aiu_i2s_dai_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||
}
|
||||
}
|
||||
|
||||
-static int __get_lrclk_div(unsigned int os, unsigned int width)
|
||||
-{
|
||||
- if (((os % 48) == 0) && (width == 24))
|
||||
- return 48;
|
||||
- else if (((os % 64) == 0) && (width == 24))
|
||||
- return 64;
|
||||
- else if (((os % 32) == 0) && (width == 16))
|
||||
- return 32;
|
||||
-
|
||||
- return -EINVAL;
|
||||
-}
|
||||
-
|
||||
/*
|
||||
* FIXME: Most of this stuff should be done using CCF when the support of
|
||||
* regmap based clocks is added
|
||||
@@ -145,41 +133,24 @@ static int __get_lrclk_div(unsigned int os, unsigned int width)
|
||||
static int __bclks_set_rate(struct aiu_i2s_dai *priv, unsigned int srate,
|
||||
unsigned int width)
|
||||
{
|
||||
- int div_lrclk, div_bclk;
|
||||
+ int div_bclk;
|
||||
unsigned int os;
|
||||
u32 val;
|
||||
|
||||
/* Get the oversampling factor */
|
||||
os = DIV_ROUND_CLOSEST(clk_get_rate(priv->amclk), srate);
|
||||
|
||||
- /* Get the divider between bclk and lrclk */
|
||||
- div_lrclk = __get_lrclk_div(os, width);
|
||||
-
|
||||
- switch (div_lrclk) {
|
||||
- case 32:
|
||||
- val = AIU_I2S_DAC_CFG_AOCLK_32;
|
||||
- break;
|
||||
- case 48:
|
||||
- val = AIU_I2S_DAC_CFG_AOCLK_48;
|
||||
- break;
|
||||
- case 64:
|
||||
- val = AIU_I2S_DAC_CFG_AOCLK_64;
|
||||
- break;
|
||||
- default:
|
||||
- return -EINVAL;
|
||||
- }
|
||||
-
|
||||
/* Set the divider between lrclk and bclk */
|
||||
regmap_update_bits(priv->regmap, AIU_I2S_DAC_CFG,
|
||||
AIU_I2S_DAC_CFG_PAYLOAD_SIZE_MASK,
|
||||
- val);
|
||||
+ AIU_I2S_DAC_CFG_AOCLK_64);
|
||||
|
||||
regmap_update_bits(priv->regmap, AIU_CODEC_DAC_LRCLK_CTRL,
|
||||
AIU_CODEC_DAC_LRCLK_CTRL_DIV_MASK,
|
||||
- AIU_CODEC_DAC_LRCLK_CTRL_DIV(div_lrclk));
|
||||
+ AIU_CODEC_DAC_LRCLK_CTRL_DIV(64));
|
||||
|
||||
/* Set the divider between blclk and amclk */
|
||||
- div_bclk = os / div_lrclk;
|
||||
+ div_bclk = os / 64;
|
||||
|
||||
/* Use CLK_MORE for the i2s divider */
|
||||
regmap_update_bits(priv->regmap, AIU_CLK_CTRL,
|
||||
--
|
||||
1.9.1
|
||||
|
11
patch/kernel/odroidc2-next/bash_to_afterinstall.patch
Normal file
11
patch/kernel/odroidc2-next/bash_to_afterinstall.patch
Normal file
|
@ -0,0 +1,11 @@
|
|||
--- a/scripts/package/builddeb
|
||||
+++ b/scripts/package/builddeb
|
||||
@@ -218,7 +218,7 @@
|
||||
for script in postinst postrm preinst prerm ; do
|
||||
mkdir -p "$tmpdir$debhookdir/$script.d"
|
||||
cat <<EOF > "$tmpdir/DEBIAN/$script"
|
||||
-#!/bin/sh
|
||||
+#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
|
@ -0,0 +1,203 @@
|
|||
diff --git a/scripts/package/builddeb b/scripts/package/builddeb
|
||||
index 6c3b038..cc9b3c0 100755
|
||||
--- a/scripts/package/builddeb
|
||||
+++ b/scripts/package/builddeb
|
||||
@@ -27,6 +27,28 @@ create_package() {
|
||||
chown -R root:root "$pdir"
|
||||
chmod -R go-w "$pdir"
|
||||
|
||||
+ # Create preinstall and post install script to remove dtb
|
||||
+ if [[ "$1" == *dtb* ]]; then
|
||||
+ echo "if [ -d /boot/dtb-$version ]; then mv /boot/dtb-$version /boot/dtb-$version.old; fi" >> $pdir/DEBIAN/preinst
|
||||
+ echo "if [ -d /boot/dtb.old ]; then rm -rf /boot/dtb.old; fi" >> $pdir/DEBIAN/preinst
|
||||
+ echo "if [ -d /dtb ]; then mv /dtb /dtb.old; fi" >> $pdir/DEBIAN/preinst
|
||||
+ echo "if [ -d /boot/dtb ]; then mv /boot/dtb /boot/dtb.old; fi" >> $pdir/DEBIAN/preinst
|
||||
+ echo "exit 0" >> $pdir/DEBIAN/preinst
|
||||
+ chmod 775 $pdir/DEBIAN/preinst
|
||||
+ #
|
||||
+ echo "if [ -d /boot/dtb-$version.old ]; then rm -rf /boot/dtb-$version.old; fi" >> $pdir/DEBIAN/postinst
|
||||
+ echo "ln -sf dtb-$version /boot/dtb > /dev/null 2>&1 || mv /boot/dtb-$version /boot/dtb" >> $pdir/DEBIAN/postinst
|
||||
+ echo "exit 0" >> $pdir/DEBIAN/postinst
|
||||
+ chmod 775 $pdir/DEBIAN/postinst
|
||||
+ fi
|
||||
+
|
||||
+ # Create postinstall script for headers
|
||||
+ if [[ "$1" == *headers* ]]; then
|
||||
+ echo "cd /usr/src/linux-headers-$version; echo \"Compiling headers - please wait ...\"; make -s scripts >/dev/null 2>&1" >> $pdir/DEBIAN/postinst
|
||||
+ echo "exit 0" >> $pdir/DEBIAN/postinst
|
||||
+ chmod 775 $pdir/DEBIAN/postinst
|
||||
+ fi
|
||||
+
|
||||
# Create the package
|
||||
dpkg-gencontrol $forcearch -Vkernel:debarch="${debarch}" -p$pname -P"$pdir"
|
||||
dpkg --build "$pdir" ..
|
||||
@@ -93,11 +115,13 @@ tmpdir="$objtree/debian/tmp"
|
||||
fwdir="$objtree/debian/fwtmp"
|
||||
kernel_headers_dir="$objtree/debian/hdrtmp"
|
||||
libc_headers_dir="$objtree/debian/headertmp"
|
||||
+dtb_dir="$objtree/debian/dtbtmp"
|
||||
dbg_dir="$objtree/debian/dbgtmp"
|
||||
-packagename=linux-image-$version
|
||||
-fwpackagename=linux-firmware-image-$version
|
||||
-kernel_headers_packagename=linux-headers-$version
|
||||
-libc_headers_packagename=linux-libc-dev
|
||||
+packagename=linux-image-next"$LOCALVERSION"
|
||||
+fwpackagename=linux-firmware-image-next"$LOCALVERSION"
|
||||
+kernel_headers_packagename=linux-headers-next"$LOCALVERSION"
|
||||
+dtb_packagename=linux-dtb-next"$LOCALVERSION"
|
||||
+libc_headers_packagename=linux-libc-dev-next"$LOCALVERSION"
|
||||
dbg_packagename=$packagename-dbg
|
||||
debarch=
|
||||
forcearch=
|
||||
@@ -124,7 +148,9 @@ esac
|
||||
BUILD_DEBUG="$(grep -s '^CONFIG_DEBUG_INFO=y' $KCONFIG_CONFIG || true)"
|
||||
|
||||
# Setup the directory structure
|
||||
-rm -rf "$tmpdir" "$fwdir" "$kernel_headers_dir" "$libc_headers_dir" "$dbg_dir" $objtree/debian/files
|
||||
+rm -rf "$tmpdir" "$fwdir" "$kernel_headers_dir" "$libc_headers_dir" "$dbg_dir" "$dtb_dir" $objtree/debian/files
|
||||
+mkdir -m 755 -p "$dtb_dir/DEBIAN"
|
||||
+mkdir -p "$dtb_dir/boot/dtb-$version" "$dtb_dir/usr/share/doc/$dtb_packagename"
|
||||
mkdir -m 755 -p "$tmpdir/DEBIAN"
|
||||
mkdir -p "$tmpdir/lib" "$tmpdir/boot"
|
||||
mkdir -p "$fwdir/lib/firmware/$version/"
|
||||
@@ -183,6 +209,11 @@ if grep -q '^CONFIG_MODULES=y' $KCONFIG_CONFIG ; then
|
||||
fi
|
||||
fi
|
||||
|
||||
+if grep -q '^CONFIG_OF=y' $KCONFIG_CONFIG ; then
|
||||
+ #mkdir -p "$tmpdir/boot/dtb"
|
||||
+ INSTALL_DTBS_PATH="$dtb_dir/boot/dtb-$version" $MAKE KBUILD_SRC= dtbs_install
|
||||
+fi
|
||||
+
|
||||
if [ "$ARCH" != "um" ]; then
|
||||
$MAKE headers_check KBUILD_SRC=
|
||||
$MAKE headers_install KBUILD_SRC= INSTALL_HDR_PATH="$libc_headers_dir/usr"
|
||||
@@ -195,7 +226,7 @@ fi
|
||||
# so do we; recent versions of dracut and initramfs-tools will obey this.
|
||||
debhookdir=${KDEB_HOOKDIR:-/etc/kernel}
|
||||
if grep -q '^CONFIG_BLK_DEV_INITRD=y' $KCONFIG_CONFIG; then
|
||||
- want_initrd=Yes
|
||||
+ want_initrd=Yes
|
||||
else
|
||||
want_initrd=No
|
||||
fi
|
||||
@@ -207,9 +238,11 @@ for script in postinst postrm preinst prerm ; do
|
||||
set -e
|
||||
|
||||
# Pass maintainer script parameters to hook scripts
|
||||
+
|
||||
export DEB_MAINT_PARAMS="\$*"
|
||||
|
||||
# Tell initramfs builder whether it's wanted
|
||||
+
|
||||
export INITRD=$want_initrd
|
||||
|
||||
test -d $debhookdir/$script.d && run-parts --arg="$version" --arg="/$installed_image_path" $debhookdir/$script.d
|
||||
@@ -218,6 +251,55 @@ EOF
|
||||
chmod 755 "$tmpdir/DEBIAN/$script"
|
||||
done
|
||||
|
||||
+##
|
||||
+## Create sym link to kernel image
|
||||
+##
|
||||
+sed -e "s/set -e//g" -i $tmpdir/DEBIAN/postinst
|
||||
+sed -e "s/exit 0//g" -i $tmpdir/DEBIAN/postinst
|
||||
+cat >> $tmpdir/DEBIAN/postinst <<EOT
|
||||
+if [ "\$(grep nand /proc/partitions)" != "" ] && [ "\$(grep mmc /proc/partitions)" = "" ]; then
|
||||
+mkimage -A arm -O linux -T kernel -C none -a "0x40008000" -e "0x40008000" -n "Linux kernel" -d /$installed_image_path /boot/uImage > /dev/null 2>&1
|
||||
+cp /boot/uImage /tmp/uImage
|
||||
+sync
|
||||
+mountpoint -q /boot || mount /boot
|
||||
+cp /tmp/uImage /boot/uImage
|
||||
+rm -f /$installed_image_path
|
||||
+else
|
||||
+ln -sf $(basename $installed_image_path) /boot/zImage > /dev/null 2>&1 || mv /$installed_image_path /boot/zImage
|
||||
+fi
|
||||
+touch /boot/.next
|
||||
+exit 0
|
||||
+EOT
|
||||
+##
|
||||
+## FAT install workaround
|
||||
+##
|
||||
+sed -e "s/set -e//g" -i $tmpdir/DEBIAN/preinst
|
||||
+sed -e "s/exit 0//g" -i $tmpdir/DEBIAN/preinst
|
||||
+cat >> $tmpdir/DEBIAN/preinst <<EOT
|
||||
+# exit if we are running chroot
|
||||
+if [ "\$(stat -c %d:%i /)" != "\$(stat -c %d:%i /proc/1/root/.)" ]; then exit 0; fi
|
||||
+
|
||||
+check_and_unmount (){
|
||||
+boot_device=\$(mountpoint -d /boot)
|
||||
+
|
||||
+for file in /dev/* ; do
|
||||
+ CURRENT_DEVICE=\$(printf "%d:%d" \$(stat --printf="0x%t 0x%T" \$file))
|
||||
+ if [[ "\$CURRENT_DEVICE" = "\$boot_device" ]]; then
|
||||
+ boot_partition=\$file
|
||||
+ break;
|
||||
+ fi
|
||||
+done
|
||||
+
|
||||
+bootfstype=\$(blkid -s TYPE -o value \$boot_partition)
|
||||
+if [ "\$bootfstype" = "vfat" ]; then
|
||||
+umount /boot;
|
||||
+rm -f /boot/System.map* /boot/config* /boot/vmlinuz* /boot/zImage /boot/uImage
|
||||
+fi
|
||||
+}
|
||||
+mountpoint -q /boot && check_and_unmount
|
||||
+EOT
|
||||
+echo "exit 0" >> $tmpdir/DEBIAN/preinst
|
||||
+
|
||||
# Try to determine maintainer and email values
|
||||
if [ -n "$DEBEMAIL" ]; then
|
||||
email=$DEBEMAIL
|
||||
@@ -328,16 +414,24 @@ fi
|
||||
(cd $objtree; find arch/$SRCARCH/include Module.symvers include scripts -type f) >> "$objtree/debian/hdrobjfiles"
|
||||
destdir=$kernel_headers_dir/usr/src/linux-headers-$version
|
||||
mkdir -p "$destdir"
|
||||
+######################## headers patch
|
||||
+ZACNI=$(pwd)
|
||||
+cd $destdir
|
||||
+patch -p1 < /tmp/headers-debian-byteshift.patch
|
||||
+cd $ZACNI
|
||||
+######################## headers patch
|
||||
(cd $srctree; tar -c -f - -T -) < "$objtree/debian/hdrsrcfiles" | (cd $destdir; tar -xf -)
|
||||
(cd $objtree; tar -c -f - -T -) < "$objtree/debian/hdrobjfiles" | (cd $destdir; tar -xf -)
|
||||
(cd $objtree; cp $KCONFIG_CONFIG $destdir/.config) # copy .config manually to be where it's expected to be
|
||||
ln -sf "/usr/src/linux-headers-$version" "$kernel_headers_dir/lib/modules/$version/build"
|
||||
rm -f "$objtree/debian/hdrsrcfiles" "$objtree/debian/hdrobjfiles"
|
||||
|
||||
+(cd "$destdir"; make M=scripts clean)
|
||||
+
|
||||
cat <<EOF >> debian/control
|
||||
|
||||
Package: $kernel_headers_packagename
|
||||
-Provides: linux-headers, linux-headers-2.6
|
||||
+Provides: linux-headers
|
||||
Architecture: any
|
||||
Description: Linux kernel headers for $KERNELRELEASE on \${kernel:debarch}
|
||||
This package provides kernel header files for $KERNELRELEASE on \${kernel:debarch}
|
||||
@@ -363,6 +457,16 @@ fi
|
||||
|
||||
cat <<EOF >> debian/control
|
||||
|
||||
+Package: $dtb_packagename
|
||||
+Architecture: any
|
||||
+Description: Linux DTB, version $version
|
||||
+ This package contains device blobs from the Linux kernel, version $version.
|
||||
+EOF
|
||||
+
|
||||
+create_package "$dtb_packagename" "$dtb_dir"
|
||||
+
|
||||
+cat <<EOF >> debian/control
|
||||
+
|
||||
Package: $libc_headers_packagename
|
||||
Section: devel
|
||||
Provides: linux-kernel-headers
|
||||
@@ -374,7 +478,7 @@ EOF
|
||||
|
||||
if [ "$ARCH" != "um" ]; then
|
||||
create_package "$kernel_headers_packagename" "$kernel_headers_dir"
|
||||
- create_package "$libc_headers_packagename" "$libc_headers_dir"
|
||||
+# create_package "$libc_headers_packagename" "$libc_headers_dir"
|
||||
fi
|
||||
|
||||
create_package "$packagename" "$tmpdir"
|
Loading…
Add table
Add a link
Reference in a new issue