diff --git a/packages/graphics/bcm2835-driver/package.mk b/packages/graphics/bcm2835-driver/package.mk index 816c9acb0c..e1ae02b56f 100644 --- a/packages/graphics/bcm2835-driver/package.mk +++ b/packages/graphics/bcm2835-driver/package.mk @@ -17,7 +17,7 @@ ################################################################################ PKG_NAME="bcm2835-driver" -PKG_VERSION="b038854" +PKG_VERSION="4b79411" PKG_ARCH="any" PKG_LICENSE="nonfree" PKG_SITE="http://www.broadcom.com" diff --git a/packages/linux/package.mk b/packages/linux/package.mk index acd4fb95b9..bc1e4e0501 100644 --- a/packages/linux/package.mk +++ b/packages/linux/package.mk @@ -59,7 +59,7 @@ case "$LINUX" in PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET imx6-status-led imx6-soc-fan irqbalanced" ;; *) - PKG_VERSION="4.10.9" + PKG_VERSION="4.10.11" PKG_URL="http://www.kernel.org/pub/linux/kernel/v4.x/$PKG_NAME-$PKG_VERSION.tar.xz" PKG_PATCH_DIRS="default" ;; diff --git a/packages/linux/patches/default/linux-053-spinelplus-remote-0.2.patch b/packages/linux/patches/default/linux-053-spinelplus-remote-0.2.patch index ca86427992..1b645d5ebe 100644 --- a/packages/linux/patches/default/linux-053-spinelplus-remote-0.2.patch +++ b/packages/linux/patches/default/linux-053-spinelplus-remote-0.2.patch @@ -1,7 +1,37 @@ -diff -Naur linux-3.19/drivers/hid/hid-core.c linux-3.19.patch/drivers/hid/hid-core.c ---- linux-3.19/drivers/hid/hid-core.c 2015-02-09 03:54:22.000000000 +0100 -+++ linux-3.19.patch/drivers/hid/hid-core.c 2015-02-11 00:06:14.966131308 +0100 -@@ -1886,6 +1886,10 @@ +diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig +index cd4599c..86b22f7 100644 +--- a/drivers/hid/Kconfig ++++ b/drivers/hid/Kconfig +@@ -768,6 +768,12 @@ config HID_STEELSERIES + ---help--- + Support for Steelseries SRW-S1 steering wheel + ++config HID_SPINELPLUS ++ tristate "Spinel Plus remote control" ++ depends on USB_HID ++ ---help--- ++ Say Y here if you have a Spinel Plus (0471:206c/20cc/0613/2168) remote ++ + config HID_SUNPLUS + tristate "Sunplus wireless desktop" + depends on HID +diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile +index 86b2b57..89dbf38 100644 +--- a/drivers/hid/Makefile ++++ b/drivers/hid/Makefile +@@ -88,6 +88,7 @@ obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o + obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o + obj-$(CONFIG_HID_SONY) += hid-sony.o + obj-$(CONFIG_HID_SPEEDLINK) += hid-speedlink.o ++obj-$(CONFIG_HID_SPINELPLUS) += hid-spinelplus.o + obj-$(CONFIG_HID_STEELSERIES) += hid-steelseries.o + obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o + obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o +diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c +index 2b89c70..c83cfdc 100644 +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -2014,6 +2014,10 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, { HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_6000) }, { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, @@ -11,25 +41,28 @@ diff -Naur linux-3.19/drivers/hid/hid-core.c linux-3.19.patch/drivers/hid/hid-co + { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_4) }, { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, HID_ANY_ID) }, { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) }, - #if IS_ENABLED(CONFIG_HID_ROCCAT) -diff -Naur linux-3.19/drivers/hid/hid-ids.h linux-3.19.patch/drivers/hid/hid-ids.h ---- linux-3.19/drivers/hid/hid-ids.h 2015-02-09 03:54:22.000000000 +0100 -+++ linux-3.19.patch/drivers/hid/hid-ids.h 2015-02-11 00:04:45.885977057 +0100 -@@ -743,6 +743,10 @@ - + { HID_USB_DEVICE(USB_VENDOR_ID_RISO_KAGAKU, USB_DEVICE_ID_RI_KA_WEBMAIL) }, +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index 9845189..e016cd1 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -813,6 +813,10 @@ + #define USB_VENDOR_ID_PHILIPS 0x0471 #define USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE 0x0617 +#define USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_1 0x206c +#define USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_2 0x20cc +#define USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_3 0x0613 +#define USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_4 0x2168 - + #define USB_VENDOR_ID_PI_ENGINEERING 0x05f3 #define USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL 0xff -diff -Naur linux-3.19/drivers/hid/hid-spinelplus.c linux-3.19.patch/drivers/hid/hid-spinelplus.c ---- linux-3.19/drivers/hid/hid-spinelplus.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.19.patch/drivers/hid/hid-spinelplus.c 2015-02-11 00:04:45.886977059 +0100 -@@ -0,0 +1,104 @@ +diff --git a/drivers/hid/hid-spinelplus.c b/drivers/hid/hid-spinelplus.c +new file mode 100644 +index 0000000..381c7b3 +--- /dev/null ++++ b/drivers/hid/hid-spinelplus.c +@@ -0,0 +1,95 @@ +/* + * HID driver for "PHILIPS MCE USB IR Receiver- Spinel plus" remotes + * @@ -122,43 +155,6 @@ diff -Naur linux-3.19/drivers/hid/hid-spinelplus.c linux-3.19.patch/drivers/hid/ + .probe = spinelplus_probe, +}; + -+static int __init spinelplus_init(void) -+{ -+ return hid_register_driver(&spinelplus_driver); -+} ++module_hid_driver(spinelplus_driver); + -+static void __exit spinelplus_exit(void) -+{ -+ hid_unregister_driver(&spinelplus_driver); -+} -+ -+module_init(spinelplus_init); -+module_exit(spinelplus_exit); +MODULE_LICENSE("GPL"); -diff -Naur linux-3.19/drivers/hid/Kconfig linux-3.19.patch/drivers/hid/Kconfig ---- linux-3.19/drivers/hid/Kconfig 2015-02-09 03:54:22.000000000 +0100 -+++ linux-3.19.patch/drivers/hid/Kconfig 2015-02-11 00:04:45.886977059 +0100 -@@ -702,6 +702,12 @@ - ---help--- - Support for Steelseries SRW-S1 steering wheel - -+config HID_SPINELPLUS -+ tristate "Spinel Plus remote control" -+ depends on USB_HID -+ ---help--- -+ Say Y here if you have a Spinel Plus (0471:206c/20cc/0613/2168) remote -+ - config HID_SUNPLUS - tristate "Sunplus wireless desktop" - depends on HID -diff -Naur linux-3.19/drivers/hid/Makefile linux-3.19.patch/drivers/hid/Makefile ---- linux-3.19/drivers/hid/Makefile 2015-02-09 03:54:22.000000000 +0100 -+++ linux-3.19.patch/drivers/hid/Makefile 2015-02-11 00:04:45.886977059 +0100 -@@ -107,6 +107,7 @@ - obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o - obj-$(CONFIG_HID_SONY) += hid-sony.o - obj-$(CONFIG_HID_SPEEDLINK) += hid-speedlink.o -+obj-$(CONFIG_HID_SPINELPLUS) += hid-spinelplus.o - obj-$(CONFIG_HID_STEELSERIES) += hid-steelseries.o - obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o - obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o diff --git a/packages/linux/patches/default/linux-999-i915-use-legacy-turbo.patch b/packages/linux/patches/default/linux-999-i915-use-legacy-turbo.patch deleted file mode 100644 index a8df9d68d2..0000000000 --- a/packages/linux/patches/default/linux-999-i915-use-legacy-turbo.patch +++ /dev/null @@ -1,27 +0,0 @@ -From aefcd1a6b1ec22e4e0d26eb932b618c5d12f7e9c Mon Sep 17 00:00:00 2001 -From: fritsch -Date: Sun, 21 Feb 2016 12:39:16 +0100 -Subject: [PATCH] i915_irq: enable legacy turbo (4.6) - ---- - drivers/gpu/drm/i915/i915_irq.c | 7 +------ - 1 file changed, 1 insertion(+), 6 deletions(-) - -diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c -index 1c21220..6507643 100644 ---- a/drivers/gpu/drm/i915/i915_irq.c -+++ b/drivers/gpu/drm/i915/i915_irq.c -@@ -4557,12 +4557,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv) - INIT_WORK(&dev_priv->rps.work, gen6_pm_rps_work); - INIT_WORK(&dev_priv->l3_parity.error_work, ivybridge_parity_work); - -- /* Let's track the enabled rps events */ -- if (IS_VALLEYVIEW(dev_priv)) -- /* WaGsvRC0ResidencyMethod:vlv */ -- dev_priv->pm_rps_events = GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED; -- else -- dev_priv->pm_rps_events = GEN6_PM_RPS_EVENTS; -+ dev_priv->pm_rps_events = GEN6_PM_RPS_EVENTS; - - INIT_DELAYED_WORK(&dev_priv->gpu_error.hangcheck_work, - i915_hangcheck_elapsed); diff --git a/packages/tools/bcm2835-bootloader/package.mk b/packages/tools/bcm2835-bootloader/package.mk index 023e74edcd..7785340c60 100644 --- a/packages/tools/bcm2835-bootloader/package.mk +++ b/packages/tools/bcm2835-bootloader/package.mk @@ -17,7 +17,7 @@ ################################################################################ PKG_NAME="bcm2835-bootloader" -PKG_VERSION="b038854" +PKG_VERSION="4b79411" PKG_ARCH="arm" PKG_LICENSE="nonfree" PKG_SITE="http://www.broadcom.com" diff --git a/projects/Generic/linux/linux.x86_64.conf b/projects/Generic/linux/linux.x86_64.conf index 2058570baa..59474d3cee 100644 --- a/projects/Generic/linux/linux.x86_64.conf +++ b/projects/Generic/linux/linux.x86_64.conf @@ -3792,7 +3792,7 @@ CONFIG_HID_SONY=y CONFIG_SONY_FF=y # CONFIG_HID_SPEEDLINK is not set # CONFIG_HID_STEELSERIES is not set -CONFIG_HID_SPINELPLUS=y +CONFIG_HID_SPINELPLUS=m CONFIG_HID_SUNPLUS=y CONFIG_HID_RMI=y # CONFIG_HID_GREENASIA is not set diff --git a/projects/RPi/devices/RPi/linux/linux.arm.conf b/projects/RPi/devices/RPi/linux/linux.arm.conf index 9105d7e0bb..cc7d26e763 100644 --- a/projects/RPi/devices/RPi/linux/linux.arm.conf +++ b/projects/RPi/devices/RPi/linux/linux.arm.conf @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 4.10.9 Kernel Configuration +# Linux/arm 4.10.11 Kernel Configuration # CONFIG_ARM=y CONFIG_ARM_HAS_SG_CHAIN=y @@ -2513,6 +2513,11 @@ CONFIG_VIDEO_CX25840=m # # Sensors used on soc_camera driver # + +# +# Media SPI Adapters +# +CONFIG_CXD2880_SPI_DRV=m CONFIG_MEDIA_TUNER=m CONFIG_MEDIA_TUNER_SIMPLE=m CONFIG_MEDIA_TUNER_TDA8290=m @@ -3034,7 +3039,7 @@ CONFIG_HID_SONY=y CONFIG_SONY_FF=y # CONFIG_HID_SPEEDLINK is not set # CONFIG_HID_STEELSERIES is not set -CONFIG_HID_SPINELPLUS=y +CONFIG_HID_SPINELPLUS=m CONFIG_HID_SUNPLUS=y CONFIG_HID_RMI=y # CONFIG_HID_GREENASIA is not set diff --git a/projects/RPi/devices/RPi2/linux/linux.arm.conf b/projects/RPi/devices/RPi2/linux/linux.arm.conf index 65eadff082..acffebe6b7 100644 --- a/projects/RPi/devices/RPi2/linux/linux.arm.conf +++ b/projects/RPi/devices/RPi2/linux/linux.arm.conf @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 4.10.9 Kernel Configuration +# Linux/arm 4.10.11 Kernel Configuration # CONFIG_ARM=y CONFIG_ARM_HAS_SG_CHAIN=y @@ -2604,6 +2604,11 @@ CONFIG_VIDEO_CX25840=m # # Sensors used on soc_camera driver # + +# +# Media SPI Adapters +# +CONFIG_CXD2880_SPI_DRV=m CONFIG_MEDIA_TUNER=m CONFIG_MEDIA_TUNER_SIMPLE=m CONFIG_MEDIA_TUNER_TDA8290=m @@ -3125,7 +3130,7 @@ CONFIG_HID_SONY=y CONFIG_SONY_FF=y # CONFIG_HID_SPEEDLINK is not set # CONFIG_HID_STEELSERIES is not set -CONFIG_HID_SPINELPLUS=y +CONFIG_HID_SPINELPLUS=m CONFIG_HID_SUNPLUS=y CONFIG_HID_RMI=y # CONFIG_HID_GREENASIA is not set diff --git a/projects/RPi/patches/linux/linux-01-RPi_support.patch b/projects/RPi/patches/linux/linux-01-RPi_support.patch index 8f0f5912e5..351a6a2977 100644 --- a/projects/RPi/patches/linux/linux-01-RPi_support.patch +++ b/projects/RPi/patches/linux/linux-01-RPi_support.patch @@ -1,7 +1,7 @@ -From 89dadd30769462cf8f53757a9c6d0a99357a20bd Mon Sep 17 00:00:00 2001 +From baacde68ebc1cd0440a1a5e08589d079cd6c7479 Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Thu, 19 Feb 2015 18:47:12 +0000 -Subject: [PATCH 001/205] smsx95xx: fix crimes against truesize +Subject: [PATCH 001/207] smsx95xx: fix crimes against truesize smsc95xx is adjusting truesize when it shouldn't, and following a recent patch from Eric this is now triggering warnings. @@ -48,10 +48,10 @@ index 831aa33d078ae7d2dd57fdded5de71d1eb915f99..b77935bded8c0ff7808b00f170ff10e5 usbnet_skb_return(dev, ax_skb); } -From efb7470e3215b68a353ff289dd2169401f9b9627 Mon Sep 17 00:00:00 2001 +From fbb1fcc15096f7f7c0bcd40458c81d872bd2a70c Mon Sep 17 00:00:00 2001 From: Sam Nazarko Date: Fri, 1 Apr 2016 17:27:21 +0100 -Subject: [PATCH 002/205] smsc95xx: Experimental: Enable turbo_mode and +Subject: [PATCH 002/207] smsc95xx: Experimental: Enable turbo_mode and packetsize=2560 by default See: http://forum.kodi.tv/showthread.php?tid=285288 @@ -94,10 +94,10 @@ index b77935bded8c0ff7808b00f170ff10e594300ad0..693f163684de921404738e33244881e0 netif_dbg(dev, ifup, dev->net, "rx_urb_size=%ld\n", -From 0381daf05402920828aba3cc890842f2dac68fd4 Mon Sep 17 00:00:00 2001 +From 5945d5a3c2a2510dc11ee797ffe37dc6d600d090 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 26 Mar 2013 17:26:38 +0000 -Subject: [PATCH 003/205] Allow mac address to be set in smsc95xx +Subject: [PATCH 003/207] Allow mac address to be set in smsc95xx Signed-off-by: popcornmix --- @@ -193,10 +193,10 @@ index 693f163684de921404738e33244881e0aab92ec9..df60c989fc229bf0aab3c27e95ccd453 eth_hw_addr_random(dev->net); netif_dbg(dev, ifup, dev->net, "MAC address set to eth_random_addr\n"); -From c908aa4e3407f3f7106a9486c1614666c43b4b1b Mon Sep 17 00:00:00 2001 +From fd0412f5fd8c9647cb3a5ecbcd47023aeb11f679 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 13 Mar 2015 12:43:36 +0000 -Subject: [PATCH 004/205] Protect __release_resource against resources without +Subject: [PATCH 004/207] Protect __release_resource against resources without parents Without this patch, removing a device tree overlay can crash here. @@ -224,10 +224,10 @@ index 9b5f04404152c296af3a96132f27cfc80ffa9af9..f8a9af6e6b915812be2ba2c1c2b40106 for (;;) { tmp = *p; -From efddcc014b8b5b7331c4bb3ad197d7601849c01b Mon Sep 17 00:00:00 2001 +From 4eeef1fb3f3714896f5494124073238ce32273e7 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 18 Dec 2014 16:07:15 -0800 -Subject: [PATCH 005/205] mm: Remove the PFN busy warning +Subject: [PATCH 005/207] mm: Remove the PFN busy warning See commit dae803e165a11bc88ca8dbc07a11077caf97bbcb -- the warning is expected sometimes when using CMA. However, that commit still spams @@ -239,7 +239,7 @@ Signed-off-by: Eric Anholt 1 file changed, 2 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c -index 1a5f6655958e16ec09584c79405991dc248d2852..8068e8f926d87c02ac60f583d9b4cdefcdc2b146 100644 +index 1aec370bf9e92cea039c1917fa39dcb67bb111b9..a0f965b552cbb4cf609baf45ff9ab0be0f1400cc 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -7361,8 +7361,6 @@ int alloc_contig_range(unsigned long start, unsigned long end, @@ -252,10 +252,10 @@ index 1a5f6655958e16ec09584c79405991dc248d2852..8068e8f926d87c02ac60f583d9b4cdef goto done; } -From 3f6a1c1bf0ce1cca27569e072bb3ca42fefab7a4 Mon Sep 17 00:00:00 2001 +From fa34911d3c382707e94f89a53c82d477dee4ef9c Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 4 Dec 2015 17:41:50 +0000 -Subject: [PATCH 006/205] irq-bcm2836: Prevent spurious interrupts, and trap +Subject: [PATCH 006/207] irq-bcm2836: Prevent spurious interrupts, and trap them early The old arch-specific IRQ macros included a dsb to ensure the @@ -282,10 +282,10 @@ index e7463e3c08143acae3e8cc5682f918c6a0b07ebd..a8db33b50ad9ff83d284fa54fe4d3b65 #endif } else if (stat) { -From 6fcb12f9d9578ad59ec131b0ea9b17151073a5a5 Mon Sep 17 00:00:00 2001 +From 790049aba4d0200995b99ccd5cbb07a32f52818d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 12 Jun 2015 19:01:05 +0200 -Subject: [PATCH 007/205] irqchip: bcm2835: Add FIQ support +Subject: [PATCH 007/207] irqchip: bcm2835: Add FIQ support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -414,10 +414,10 @@ index 44d7c38dde479d771f3552e914bf8c1c1f5019f7..42ff5e6a8e0d532f5b60a1e7af7cc4d9 } -From a599690f54e2476a9f385b85c0a38c06a08a61d8 Mon Sep 17 00:00:00 2001 +From 69fb2c3f22db3eea5b784427be30bc4ad6a0c4a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 23 Oct 2015 16:26:55 +0200 -Subject: [PATCH 008/205] irqchip: irq-bcm2835: Add 2836 FIQ support +Subject: [PATCH 008/207] irqchip: irq-bcm2835: Add 2836 FIQ support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -516,10 +516,10 @@ index 42ff5e6a8e0d532f5b60a1e7af7cc4d941bd5008..eccf6ed025299cb480884f5bcbe77abf for (b = 0; b < NR_BANKS; b++) { for (i = 0; i < bank_irqs[b]; i++) { -From d9433d8cf3a7a7cc1a1c1008fc93ad8a343f10c8 Mon Sep 17 00:00:00 2001 +From 42bf7f65e39200e6d0c7d11087bda591b97c8d26 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 14 Jul 2015 10:26:09 +0100 -Subject: [PATCH 009/205] spidev: Add "spidev" compatible string to silence +Subject: [PATCH 009/207] spidev: Add "spidev" compatible string to silence warning See: https://github.com/raspberrypi/linux/issues/1054 @@ -540,10 +540,10 @@ index 9e2e099baf8ca5cc6510912a36d4ca03daeb8273..e59640942826db2ea14d0bde0ff5ab22 }; MODULE_DEVICE_TABLE(of, spidev_dt_ids); -From bb9350c60c8f9f53fd59a8e5916112ca85c24794 Mon Sep 17 00:00:00 2001 +From 0dc2ddb97fda4a39ee97c9e4c43daea3954217ba Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 30 Jun 2015 14:12:42 +0100 -Subject: [PATCH 010/205] serial: 8250: Don't crash when nr_uarts is 0 +Subject: [PATCH 010/207] serial: 8250: Don't crash when nr_uarts is 0 --- drivers/tty/serial/8250/8250_core.c | 2 ++ @@ -563,10 +563,10 @@ index 76e03a7de9cc3d790a230948f599ef2db4b93249..0a172c2e6fa288de1e080463e897ea85 for (i = 0; i < nr_uarts; i++) { struct uart_8250_port *up = &serial8250_ports[i]; -From ee4b51cc466e457402fc5e60bf316b874e96f78a Mon Sep 17 00:00:00 2001 +From f370bd05638bc48530ad6810462e71e6b12ab342 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 3 Jan 2017 18:25:01 +0000 -Subject: [PATCH 011/205] Revert "pinctrl: bcm2835: switch to GPIOLIB_IRQCHIP" +Subject: [PATCH 011/207] Revert "pinctrl: bcm2835: switch to GPIOLIB_IRQCHIP" This reverts commit 85ae9e512f437cd09bf61564bdba29ab88bab3e3. --- @@ -860,10 +860,10 @@ index 85d0091128644c446aed878e87769e82c77c3ebf..4f2621272bfd5cbc0d691d2fabe89e2e if (IS_ERR(pc->pctl_dev)) { gpiochip_remove(&pc->gpio_chip); -From 53e7a001e701d9c968504a1d8d0b016c18c42652 Mon Sep 17 00:00:00 2001 +From bc117187ba3fb129db217a5361f821432e4109a5 Mon Sep 17 00:00:00 2001 From: notro Date: Thu, 10 Jul 2014 13:59:47 +0200 -Subject: [PATCH 012/205] pinctrl-bcm2835: Set base to 0 give expected gpio +Subject: [PATCH 012/207] pinctrl-bcm2835: Set base to 0 give expected gpio numbering Signed-off-by: Noralf Tronnes @@ -885,10 +885,10 @@ index 4f2621272bfd5cbc0d691d2fabe89e2ee428d6db..5b7cb4c415e19f98e25b221ab0ad36b6 .can_sleep = false, }; -From cff5be96f67aca139c96f30eb1058b24aadb15a5 Mon Sep 17 00:00:00 2001 +From ab0b571b17a56fb52f865091674cadb3f44ebcf8 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 26 Feb 2015 09:58:22 +0000 -Subject: [PATCH 013/205] pinctrl-bcm2835: Only request the interrupts listed +Subject: [PATCH 013/207] pinctrl-bcm2835: Only request the interrupts listed in the DTB Although the GPIO controller can generate three interrupts (four counting @@ -915,10 +915,10 @@ index 5b7cb4c415e19f98e25b221ab0ad36b6885dae4c..6351fe7f8e314ac5ebb102dd20847b38 pc->irq_data[i].irqgroup = i; -From 04e6a8e84aa2c3574c66380434816fdb6751fa74 Mon Sep 17 00:00:00 2001 +From 55bad162a0d6139ead02e306c8fa554d3e9faf88 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 24 Jun 2015 14:10:44 +0100 -Subject: [PATCH 014/205] spi-bcm2835: Support pin groups other than 7-11 +Subject: [PATCH 014/207] spi-bcm2835: Support pin groups other than 7-11 The spi-bcm2835 driver automatically uses GPIO chip-selects due to some unreliability of the native ones. In doing so it chooses the @@ -999,10 +999,10 @@ index f35cc10772f6670397ea923ad30158270dd68578..5dfe20ffc2866fa6789825016c585175 /* and set up the "mode" and level */ dev_info(&spi->dev, "setting up native-CS%i as GPIO %i\n", -From 6b0647cff1fd3c05ff69ad73d56865c8d5b4ca7f Mon Sep 17 00:00:00 2001 +From 99ad98c98d1510a915e6652c491dfc64276e59d9 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 1 Jul 2016 22:09:24 +0100 -Subject: [PATCH 015/205] spi-bcm2835: Disable forced software CS +Subject: [PATCH 015/207] spi-bcm2835: Disable forced software CS Select software CS in bcm2708_common.dtsi, and disable the automatic conversion in the driver to allow hardware CS to be re-enabled with an @@ -1036,10 +1036,10 @@ index 5dfe20ffc2866fa6789825016c585175a29705b6..8493474d286f7a1ac6454a22c61c8c2c return 0; } -From bc2bf0667ac142bda0a88c6d0125afc02d103981 Mon Sep 17 00:00:00 2001 +From 76472aaf6c96c22ec85152d2b55d012f210e1f97 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 8 Nov 2016 21:35:38 +0000 -Subject: [PATCH 016/205] spi-bcm2835: Remove unused code +Subject: [PATCH 016/207] spi-bcm2835: Remove unused code --- drivers/spi/spi-bcm2835.c | 61 ----------------------------------------------- @@ -1127,10 +1127,10 @@ index 8493474d286f7a1ac6454a22c61c8c2cef9121bf..33d75ad38a7f77d085321ace9101900a } -From 09ada1636f805035c0d21047972b9e6453b648d2 Mon Sep 17 00:00:00 2001 +From 4e8925f75e3115cc11e13a34a773de16fcb9c584 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Wed, 3 Jun 2015 12:26:13 +0200 -Subject: [PATCH 017/205] ARM: bcm2835: Set Serial number and Revision +Subject: [PATCH 017/207] ARM: bcm2835: Set Serial number and Revision MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -1183,10 +1183,10 @@ index 0c1edfc98696da0e0bb7f4a18cdfbcdd27a9795d..8f152266ba9b470df2eaaed9ebcf158e static const char * const bcm2835_compat[] = { -From 4608ee7b3f7a981ff7c02664fbea9dce2f798b8c Mon Sep 17 00:00:00 2001 +From 738cb2c8f746e258a3a83c16c9b2a23f735974d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Sat, 3 Oct 2015 22:22:55 +0200 -Subject: [PATCH 018/205] dmaengine: bcm2835: Load driver early and support +Subject: [PATCH 018/207] dmaengine: bcm2835: Load driver early and support legacy API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 @@ -1289,10 +1289,10 @@ index e18dc596cf2447fa9ef7e41b62d9396e29043426..80d35f760b4a4a51e60c355a84d538ba MODULE_ALIAS("platform:bcm2835-dma"); MODULE_DESCRIPTION("BCM2835 DMA engine driver"); -From 93fe848bc1014552c503a33159879ee5e9b76463 Mon Sep 17 00:00:00 2001 +From e2240cc99fea8b6d1a6d9bf81a9818940a641cd1 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 25 Jan 2016 17:25:12 +0000 -Subject: [PATCH 019/205] firmware: Updated mailbox header +Subject: [PATCH 019/207] firmware: Updated mailbox header --- include/soc/bcm2835/raspberrypi-firmware.h | 9 +++++++++ @@ -1353,10 +1353,10 @@ index cb979ad90401e299344dd5fae38d09c489d8bd58..30fb37fe175df604a738258a2a632bca RPI_FIRMWARE_VCHIQ_INIT = 0x00048010, -From d9439af751c350c29a6923da191df377a6803e76 Mon Sep 17 00:00:00 2001 +From 8839d76db87798c9f5636426483f6492d1d09c44 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 15 Jun 2016 16:48:41 +0100 -Subject: [PATCH 020/205] rtc: Add SPI alias for pcf2123 driver +Subject: [PATCH 020/207] rtc: Add SPI alias for pcf2123 driver Without this alias, Device Tree won't cause the driver to be loaded. @@ -1376,10 +1376,10 @@ index 8895f77726e8da5444afcd602dceff8f25a9b3fd..1833b8853ceb0e6147cceb93a00e558c MODULE_LICENSE("GPL"); +MODULE_ALIAS("spi:rtc-pcf2123"); -From 278a63c53616eabd17fe4fd244c48a1e21aa917c Mon Sep 17 00:00:00 2001 +From e25141791ab991410ffc7a7d3181c2af5ce6baa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 7 Oct 2016 16:50:59 +0200 -Subject: [PATCH 021/205] watchdog: bcm2835: Support setting reboot partition +Subject: [PATCH 021/207] watchdog: bcm2835: Support setting reboot partition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -1503,10 +1503,10 @@ index c32c45bd8b097889c8f322255fa63c8ed507d6ab..ef02dfa23aa774e1cdf75f935c5de985 register_restart_handler(&wdt->restart_handler); if (pm_power_off == NULL) -From 2dd240a540383c3c885cac574a0d3ae515febe59 Mon Sep 17 00:00:00 2001 +From 6b9d92b0d5cc7b9315e9005082e970c12db3f298 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 5 Apr 2016 19:40:12 +0100 -Subject: [PATCH 022/205] reboot: Use power off rather than busy spinning when +Subject: [PATCH 022/207] reboot: Use power off rather than busy spinning when halt is requested --- @@ -1529,10 +1529,10 @@ index 3fa867a2aae672755c6ce6448f4148c989dbf964..80dca8dcd6709034b643c6a3f35729e0 /* -From cfe24e5c8aaf64338cf89d2420e878962053c76c Mon Sep 17 00:00:00 2001 +From 4554a69476b903e1695aba20775bfa35fbe4635b Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 9 Nov 2016 13:02:52 +0000 -Subject: [PATCH 023/205] bcm: Make RASPBERRYPI_POWER depend on PM +Subject: [PATCH 023/207] bcm: Make RASPBERRYPI_POWER depend on PM --- drivers/soc/bcm/Kconfig | 1 + @@ -1551,10 +1551,10 @@ index a39b0d58ddd0fdf0ac1cc7295f8aafb12546e226..e037a6dd79d1881a09e3ca9115782709 help This enables support for the RPi power domains which can be enabled -From 4985db704f0037236ecc8798dedb9cdc00a55417 Mon Sep 17 00:00:00 2001 +From 74abf67eb9960a1060318e6d4ba9ff0842a01acb Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Fri, 2 Sep 2016 16:45:27 +0100 -Subject: [PATCH 024/205] Register the clocks early during the boot process, so +Subject: [PATCH 024/207] Register the clocks early during the boot process, so that special/critical clocks can get enabled early on in the boot process avoiding the risk of disabling a clock, pll_divider or pll when a claiming driver fails to install propperly - maybe it needs to defer. @@ -1599,10 +1599,10 @@ index 0d14409097e777ce4546de30e9278fdebf74ec44..093694e00caec6e133eb26712f890691 MODULE_AUTHOR("Eric Anholt "); MODULE_DESCRIPTION("BCM2835 clock driver"); -From 85c69bab8c2b75529746ece517cd4c367b1f5358 Mon Sep 17 00:00:00 2001 +From dab79575e259529f997493d4ef56f021ddf2d33a Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 6 Dec 2016 17:05:39 +0000 -Subject: [PATCH 025/205] bcm2835-rng: Avoid initialising if already enabled +Subject: [PATCH 025/207] bcm2835-rng: Avoid initialising if already enabled Avoids the 0x40000 cycles of warmup again if firmware has already used it --- @@ -1628,10 +1628,10 @@ index 574211a495491d9d6021dcaefe4274a63ed02055..e66c0fca8c6090e32f72796c0877a1cf err = hwrng_register(&bcm2835_rng_ops); if (err) { -From 5e54c7da6a8c38c7fe653ef823ddf91cb67aaccd Mon Sep 17 00:00:00 2001 +From 1a1f6f1f4972671dd91176e4ba197ace6d28e77f Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 24 Aug 2016 16:28:44 +0100 -Subject: [PATCH 026/205] kbuild: Ignore dtco targets when filtering symbols +Subject: [PATCH 026/207] kbuild: Ignore dtco targets when filtering symbols --- scripts/Kbuild.include | 2 +- @@ -1651,10 +1651,10 @@ index 179219845dfcdfbeb586d12c5ec1296095d9fbf4..e0743e44f84188667a0c322e8c3d36f1 esac | tr ";" "\n" | sed -rn 's/^.*=== __KSYM_(.*) ===.*$$/KSYM_\1/p' -From 7aec9bc7eb5ea70ad5a6e55f223a7cad989d05d1 Mon Sep 17 00:00:00 2001 +From 063f0171f08f743a667d782ab4d9b1039aae15db Mon Sep 17 00:00:00 2001 From: Robert Tiemann Date: Mon, 20 Jul 2015 11:01:25 +0200 -Subject: [PATCH 027/205] BCM2835_DT: Fix I2S register map +Subject: [PATCH 027/207] BCM2835_DT: Fix I2S register map --- Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt | 4 ++-- @@ -1692,10 +1692,10 @@ index 65783de0aedf3da79adc36fd077b7a89954ddb6b..a89fe4220fdc3f26f75ee66daf187554 dmas = <&dma 2>, <&dma 3>; -From ff33941a43b9ffc7e0ba4b8c61292b034bb025a7 Mon Sep 17 00:00:00 2001 +From 8807a0fbf7da8772a87324ab8b785515dee85ab8 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 12 May 2013 12:24:19 +0100 -Subject: [PATCH 028/205] Main bcm2708/bcm2709 linux port +Subject: [PATCH 028/207] Main bcm2708/bcm2709 linux port MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -1902,10 +1902,10 @@ index cfb4b4496dd9f61362dea012176c146120fada07..d9c6c217c4d6a2408abe2665bf7f2700 MODULE_AUTHOR("Lubomir Rintel "); MODULE_DESCRIPTION("BCM2835 mailbox IPC driver"); -From 2bc6c5b85262d62fbc887915b6fc9d31021a60df Mon Sep 17 00:00:00 2001 +From 98f6a0b07cb78c31428988f44cba75b846f567ff Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 May 2013 19:46:17 +0100 -Subject: [PATCH 029/205] Add dwc_otg driver +Subject: [PATCH 029/207] Add dwc_otg driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -62962,10 +62962,10 @@ index 0000000000000000000000000000000000000000..cdc9963176e5a4a0d5250613b61e26c5 +test_main(); +0; -From e8acef74f0dd0803701ec2e6daba26319e2cfd07 Mon Sep 17 00:00:00 2001 +From a27f8f119927b08a3e453e10a7608cbf183332c8 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 17 Jun 2015 17:06:34 +0100 -Subject: [PATCH 030/205] bcm2708 framebuffer driver +Subject: [PATCH 030/207] bcm2708 framebuffer driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -66424,10 +66424,10 @@ index 3c14e43b82fefe1d32f591d1b2f61d2cd28d0fa8..7626beb6a5bb8df601ddf0f6e6909d1f +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 -From 70392df4f0ef28d386047da06706c18edde69ece Mon Sep 17 00:00:00 2001 +From 7597c74e815bbc87fce16b2c6b147a5a1e94b58f Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Fri, 22 Nov 2013 14:22:53 +0100 -Subject: [PATCH 031/205] dmaengine: Add support for BCM2708 +Subject: [PATCH 031/207] dmaengine: Add support for BCM2708 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -67058,10 +67058,10 @@ index 0000000000000000000000000000000000000000..c5bfff2765be4606077e6c8af73040ec + +#endif /* _PLAT_BCM2708_DMA_H */ -From 37f258f53d3dace314212bd80dcd71444fdd19ae Mon Sep 17 00:00:00 2001 +From d2986a520db45c66741204fee2475befae956cc7 Mon Sep 17 00:00:00 2001 From: gellert Date: Fri, 15 Aug 2014 16:35:06 +0100 -Subject: [PATCH 032/205] MMC: added alternative MMC driver +Subject: [PATCH 032/207] MMC: added alternative MMC driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -68811,10 +68811,10 @@ index 0000000000000000000000000000000000000000..4fe8d1fe44578fbefcd48f8c327ba3d0 +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Gellert Weisz"); -From a3ea8afe67e33f024422ef683c2d8845c371dd63 Mon Sep 17 00:00:00 2001 +From f81720ec986b212407834151b25aff1ff4d72581 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 25 Mar 2015 17:49:47 +0000 -Subject: [PATCH 033/205] Adding bcm2835-sdhost driver, and an overlay to +Subject: [PATCH 033/207] Adding bcm2835-sdhost driver, and an overlay to enable it BCM2835 has two SD card interfaces. This driver uses the other one. @@ -71219,10 +71219,10 @@ index 0000000000000000000000000000000000000000..a9bc79bfdbb71807819dfe2d8f165144 +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Phil Elwell"); -From bce534c287cea6200a54d82482d6e623df03c314 Mon Sep 17 00:00:00 2001 +From 7426162ae9885947c30ad4ff93a1141c2fd9ae77 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 11 May 2016 12:50:33 +0100 -Subject: [PATCH 034/205] mmc: Add MMC_QUIRK_ERASE_BROKEN for some cards +Subject: [PATCH 034/207] mmc: Add MMC_QUIRK_ERASE_BROKEN for some cards Some SD cards have been found that corrupt data when small blocks are erased. Add a quirk to indicate that ERASE should not be used, @@ -71358,10 +71358,10 @@ index 95d69d4982965aa30fb65d9ffecfad13f4e7be8f..a97b881a04f4b3294cf3ede393cde717 unsigned int erase_shift; /* if erase unit is power 2 */ unsigned int pref_erase; /* in sectors */ -From c5f59dafa94e117548ea7f3909a977a155d9d4fe Mon Sep 17 00:00:00 2001 +From f4c7f1d7edb6df67fa072c1c7c5bf66010a540a7 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:31:47 +0100 -Subject: [PATCH 035/205] cma: Add vc_cma driver to enable use of CMA +Subject: [PATCH 035/207] cma: Add vc_cma driver to enable use of CMA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -72697,10 +72697,10 @@ index 0000000000000000000000000000000000000000..be2819d5d41f9d5ed65daf8eedb94c9e + +#endif /* VC_CMA_H */ -From f82842a4ff8a2e49239d4c2111940f1bb57c8cce Mon Sep 17 00:00:00 2001 +From 2d30676ef13977655a6202581b8e4ec40c08a6a7 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 26 Mar 2012 22:15:50 +0100 -Subject: [PATCH 036/205] bcm2708: alsa sound driver +Subject: [PATCH 036/207] bcm2708: alsa sound driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -75435,10 +75435,10 @@ index 0000000000000000000000000000000000000000..af3e6eb690113fc32ce9e06bd2f0f294 + +#endif // _VC_AUDIO_DEFS_H_ -From baa22bcf6e967f45b60f7fbb628dc65771399fac Mon Sep 17 00:00:00 2001 +From 08fac748d038b4577f05d597a717f9d86a992af5 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 28 Oct 2016 15:36:43 +0100 -Subject: [PATCH 037/205] vc_mem: Add vc_mem driver for querying firmware +Subject: [PATCH 037/207] vc_mem: Add vc_mem driver for querying firmware memory addresses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 @@ -75962,10 +75962,10 @@ index 0000000000000000000000000000000000000000..20a475377eb3078ea1ecaef2b24efc35 + +#endif /* _VC_MEM_H */ -From 9ee16548e59667c343bf94bad5e676ae86ac81b2 Mon Sep 17 00:00:00 2001 +From c6bd8ab901431c52d3d0a9c358cf323eaa82213a Mon Sep 17 00:00:00 2001 From: Tim Gover Date: Tue, 22 Jul 2014 15:41:04 +0100 -Subject: [PATCH 038/205] vcsm: VideoCore shared memory service for BCM2835 +Subject: [PATCH 038/207] vcsm: VideoCore shared memory service for BCM2835 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -80372,10 +80372,10 @@ index 0000000000000000000000000000000000000000..334f36d0d697b047df2922b5f2db67f3 + +#endif /* __VMCS_SM_IOCTL_H__INCLUDED__ */ -From 517c4c7941bc3cd7e43ab67251b40769e9663b9a Mon Sep 17 00:00:00 2001 +From 6193b023c7387237575edb4c3ef10a5976cce00a Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Fri, 21 Aug 2015 23:14:48 +0100 -Subject: [PATCH 039/205] Add /dev/gpiomem device for rootless user GPIO access +Subject: [PATCH 039/207] Add /dev/gpiomem device for rootless user GPIO access Signed-off-by: Luke Wren @@ -80686,10 +80686,10 @@ index 0000000000000000000000000000000000000000..911f5b7393ed48ceed8751f06967ae64 +MODULE_DESCRIPTION("gpiomem driver for accessing GPIO from userspace"); +MODULE_AUTHOR("Luke Wren "); -From c4c23afa23d4d1358466d147fcc73fec9bba2006 Mon Sep 17 00:00:00 2001 +From 6c44e04aaee5218b4a65e152a8a4e64eaccd911e Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Sat, 5 Sep 2015 01:14:45 +0100 -Subject: [PATCH 040/205] Add SMI driver +Subject: [PATCH 040/207] Add SMI driver Signed-off-by: Luke Wren --- @@ -82640,10 +82640,10 @@ index 0000000000000000000000000000000000000000..ee3a75edfc033eeb0d90a687ffb68b10 + +#endif /* BCM2835_SMI_H */ -From 654bc49c1e71c879cf8dd5fe1e9d4636bcf2bcd1 Mon Sep 17 00:00:00 2001 +From 087fb5ba47b937f008938e0b34b50d1369294dd6 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Tue, 26 Apr 2016 14:59:21 +0000 -Subject: [PATCH 041/205] MISC: bcm2835: smi: use clock manager and fix reload +Subject: [PATCH 041/207] MISC: bcm2835: smi: use clock manager and fix reload issues Use clock manager instead of self-made clockmanager. @@ -82813,10 +82813,10 @@ index 63a4ea08b9930a3a31a985f0a1d969b488ed49ec..1261540703127d1d63b9f3c87042c6e5 return 0; } -From 6a81d97f657fa1f7138287877234f54860dba16b Mon Sep 17 00:00:00 2001 +From 2eb0a886f2da0c67dfd378574255ef86b78c6d5f Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Sat, 5 Sep 2015 01:16:10 +0100 -Subject: [PATCH 042/205] Add SMI NAND driver +Subject: [PATCH 042/207] Add SMI NAND driver Signed-off-by: Luke Wren --- @@ -83181,10 +83181,10 @@ index 0000000000000000000000000000000000000000..02adda6da18bd0ba9ab19a104975b79d + ("Driver for NAND chips using Broadcom Secondary Memory Interface"); +MODULE_AUTHOR("Luke Wren "); -From c17e2ec8e1908864e5b550f64c7e4f603386a58a Mon Sep 17 00:00:00 2001 +From b6e110c16b90795e64227fe9377fc512b8166812 Mon Sep 17 00:00:00 2001 From: Aron Szabo Date: Sat, 16 Jun 2012 12:15:55 +0200 -Subject: [PATCH 043/205] lirc: added support for RaspberryPi GPIO +Subject: [PATCH 043/207] lirc: added support for RaspberryPi GPIO lirc_rpi: Use read_current_timer to determine transmitter delay. Thanks to jjmz and others See: https://github.com/raspberrypi/linux/issues/525 @@ -84047,10 +84047,10 @@ index 0000000000000000000000000000000000000000..fb69624ccef00ddbdccf8256d6baf1b1 + +#endif -From f4a69cb9c42a873974c2c3f9470510d121df9c08 Mon Sep 17 00:00:00 2001 +From 8d2df7d6a2b0595488641743a27d042489d19ba9 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:49:20 +0100 -Subject: [PATCH 044/205] Add cpufreq driver +Subject: [PATCH 044/207] Add cpufreq driver Signed-off-by: popcornmix --- @@ -84317,10 +84317,10 @@ index 0000000000000000000000000000000000000000..414fbdc10dfbfc6e4bb47870a7af3fd5 +module_init(bcm2835_cpufreq_module_init); +module_exit(bcm2835_cpufreq_module_exit); -From b047036dab5f6f764952ba3a3c0d939a3921dd2b Mon Sep 17 00:00:00 2001 +From eca8d911b7f9f50851edb2c599b25b5533f8b10b Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 26 Mar 2013 19:24:24 +0000 -Subject: [PATCH 045/205] Added hwmon/thermal driver for reporting core +Subject: [PATCH 045/207] Added hwmon/thermal driver for reporting core temperature. Thanks Dorian MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 @@ -84486,10 +84486,10 @@ index 0000000000000000000000000000000000000000..c63fb9f9d143e19612a18fe530c7b2b3 +MODULE_DESCRIPTION("Thermal driver for bcm2835 chip"); +MODULE_LICENSE("GPL"); -From c5b98d0ea429ebed3b417504e5e8f419e5d451e6 Mon Sep 17 00:00:00 2001 +From 670180f545a43aa7f704a9f68b7f3c096b2b59a1 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 17 Jun 2015 15:44:08 +0100 -Subject: [PATCH 046/205] Add Chris Boot's i2c driver +Subject: [PATCH 046/207] Add Chris Boot's i2c driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -85154,10 +85154,10 @@ index 0000000000000000000000000000000000000000..962f2e5c7455d91bf32925d785f5f16b +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); -From a375da4ad5fa36968e60540f13fe31e55fd867f7 Mon Sep 17 00:00:00 2001 +From a043887c2df807c049c83ded26ba7a6d89f7d728 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 26 Jun 2015 14:27:06 +0200 -Subject: [PATCH 047/205] char: broadcom: Add vcio module +Subject: [PATCH 047/207] char: broadcom: Add vcio module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -85383,10 +85383,10 @@ index 0000000000000000000000000000000000000000..c19bc2075c77879563ef5e59038b5a14 +MODULE_DESCRIPTION("Mailbox userspace access"); +MODULE_LICENSE("GPL"); -From 41fe20e4956320dc3d31d1e1ee7fce61fa955d9f Mon Sep 17 00:00:00 2001 +From 4f1f8d9cf69920439a8581e1447c12c5c589a57a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 26 Jun 2015 14:25:01 +0200 -Subject: [PATCH 048/205] firmware: bcm2835: Support ARCH_BCM270x +Subject: [PATCH 048/207] firmware: bcm2835: Support ARCH_BCM270x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -85469,10 +85469,10 @@ index dd506cd3a5b874f9e1acd07efb8cd151bb6145d1..3f070bd38a91511c986e3fb114b15bd4 MODULE_AUTHOR("Eric Anholt "); MODULE_DESCRIPTION("Raspberry Pi firmware driver"); -From 5480b52dd02ff7f97da24e3c37b3f0b18eed2842 Mon Sep 17 00:00:00 2001 +From b0dca4400cf7c2d762ff55cf4a8ebb908abf4429 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Wed, 30 Jan 2013 12:45:18 +0000 -Subject: [PATCH 049/205] bcm2835: add v4l2 camera device +Subject: [PATCH 049/207] bcm2835: add v4l2 camera device - Supports raw YUV capture, preview, JPEG and H264. - Uses videobuf2 for data transfer, using dma_buf. @@ -93214,10 +93214,10 @@ index 0000000000000000000000000000000000000000..9d1d11e4a53e510c04a416d92d195a7d + +#endif /* MMAL_VCHIQ_H */ -From 76845f0703012d6d8fb5be20b06c5a6de2182dbd Mon Sep 17 00:00:00 2001 +From 6df9c87722a3a24ea071959f950cb212fb6226f4 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 11 May 2015 09:00:42 +0100 -Subject: [PATCH 050/205] scripts: Add mkknlimg and knlinfo scripts from tools +Subject: [PATCH 050/207] scripts: Add mkknlimg and knlinfo scripts from tools repo The Raspberry Pi firmware looks for a trailer on the kernel image to @@ -93737,10 +93737,10 @@ index 0000000000000000000000000000000000000000..60206de7fa9a49bd027c635306674a29 + return $trailer; +} -From dfeb7241603dbc27b0e01ca7ba468e5e8aeb4a18 Mon Sep 17 00:00:00 2001 +From 2f7fb0f4c4ff07e3e5fe8928d2c8548d2bfd587c Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 10 Aug 2015 09:49:15 +0100 -Subject: [PATCH 051/205] scripts/dtc: Update to upstream version 1.4.1 +Subject: [PATCH 051/207] scripts/dtc: Update to upstream version 1.4.1 Includes the new localfixups format. @@ -96591,10 +96591,10 @@ index ad9b05ae698b0495ecbda42ffcf4743555313a27..2595dfda020fd9e03f0beff5006f229d -#define DTC_VERSION "DTC 1.4.1-g53bf130b" +#define DTC_VERSION "DTC 1.4.1-g25efc119" -From 59665c9f14f881aa27492efc791f7a8889717d15 Mon Sep 17 00:00:00 2001 +From 4f49c95f4b8f3cddd695f555d2a7368dde68954d Mon Sep 17 00:00:00 2001 From: notro Date: Wed, 9 Jul 2014 14:46:08 +0200 -Subject: [PATCH 052/205] BCM2708: Add core Device Tree support +Subject: [PATCH 052/207] BCM2708: Add core Device Tree support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -106722,10 +106722,10 @@ index 0a07f9014944ed92a8e2e42983ae43be60b3e471..1967878a843461c3ff1f473b9a030eb0 # Bzip2 -From 1e39c8d4a91f3b5927a22edea0fc8a9bf418e336 Mon Sep 17 00:00:00 2001 +From 772529d0422a4a3bb9a56c09759ff8003c84156b Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 6 Feb 2015 13:50:57 +0000 -Subject: [PATCH 053/205] BCM270x_DT: Add pwr_led, and the required "input" +Subject: [PATCH 053/207] BCM270x_DT: Add pwr_led, and the required "input" trigger The "input" trigger makes the associated GPIO an input. This is to support @@ -106901,10 +106901,10 @@ index 569cb531094c20a9aa2db478aaa6f348d2afd7f4..aca292f4b0932f61b5bd864251fd05b9 /* set_brightness_work / blink_timer flags, atomic, private. */ unsigned long work_flags; -From 4a5f70ac27cd0ff37f371cf59c88233191241bc8 Mon Sep 17 00:00:00 2001 +From 7c08126c7ac399b8b6279f0011f8a841c37a19e6 Mon Sep 17 00:00:00 2001 From: Siarhei Siamashka Date: Mon, 17 Jun 2013 13:32:11 +0300 -Subject: [PATCH 054/205] fbdev: add FBIOCOPYAREA ioctl +Subject: [PATCH 054/207] fbdev: add FBIOCOPYAREA ioctl Based on the patch authored by Ali Gholami Rudi at https://lkml.org/lkml/2009/7/13/153 @@ -107156,10 +107156,10 @@ index fb795c3b3c178ad3cd7c9e9e4547ffd492bac181..703fa8a70574323abe2fb32599254582 __u32 dx; /* screen-relative */ __u32 dy; -From ab40d01f0b5a0502a2079a5a281ec98d497520a0 Mon Sep 17 00:00:00 2001 +From a4e8ce1dad50d58dbe39e62a4caa0f8ae8e289ff Mon Sep 17 00:00:00 2001 From: Harm Hanemaaijer Date: Thu, 20 Jun 2013 20:21:39 +0200 -Subject: [PATCH 055/205] Speed up console framebuffer imageblit function +Subject: [PATCH 055/207] Speed up console framebuffer imageblit function Especially on platforms with a slower CPU but a relatively high framebuffer fill bandwidth, like current ARM devices, the existing @@ -107368,10 +107368,10 @@ index a2bb276a8b2463eee98eb237c4647bc00cd93601..436494fba15abecb400ef28688466faf start_index, pitch_index); } else -From 59e3726a8991d09fc999df2ba45d1019d2ddb6ca Mon Sep 17 00:00:00 2001 +From 58afcdac1743d08559f3306260e4d2cb81ea7d48 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 8 May 2013 11:46:50 +0100 -Subject: [PATCH 056/205] enabling the realtime clock 1-wire chip DS1307 and +Subject: [PATCH 056/207] enabling the realtime clock 1-wire chip DS1307 and 1-wire on GPIO4 (as a module) 1-wire: Add support for configuring pin for w1-gpio kernel module @@ -107621,10 +107621,10 @@ index d58594a3232492e33f1dd4babd3798b03e0f0203..feae94256256316fd9d850c3d83325af unsigned int ext_pullup_enable_pin; unsigned int pullup_duration; -From b5385afea932d6a3a9d6eb70386e87431f4d42d8 Mon Sep 17 00:00:00 2001 +From 4c8fbe431a13f11fd3bfd1b082cec3d5377092f8 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 18 Dec 2013 22:16:19 +0000 -Subject: [PATCH 057/205] config: Enable CONFIG_MEMCG, but leave it disabled +Subject: [PATCH 057/207] config: Enable CONFIG_MEMCG, but leave it disabled (due to memory cost). Enable with cgroup_enable=memory. --- @@ -107674,10 +107674,10 @@ index 53bbca7c48598e44fa5e45f88626027749ca8932..62d610c934f80265a889d968c4880a71 * css_tryget_online_from_dir - get corresponding css from a cgroup dentry * @dentry: directory dentry of interest -From 89a7ee13625856c0f0da3ae25f90c087ae859284 Mon Sep 17 00:00:00 2001 +From 2521c8f827c44bf1c461bb0fc65108cad4c1e1a6 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 14 Jul 2014 22:02:09 +0100 -Subject: [PATCH 058/205] hid: Reduce default mouse polling interval to 60Hz +Subject: [PATCH 058/207] hid: Reduce default mouse polling interval to 60Hz Reduces overhead when using X --- @@ -107713,10 +107713,10 @@ index 333108ef18cf2f3f94ee3816b2ba6522017295b6..da0ee3beeeed3a223ea6859f52a81e99 ret = -ENOMEM; if (usb_endpoint_dir_in(endpoint)) { -From f65d5cfaa73c1bf1d8c3964238f4183e45bff419 Mon Sep 17 00:00:00 2001 +From 794bb024534f998009b34366bea24719e5051d7c Mon Sep 17 00:00:00 2001 From: Gordon Hollingworth Date: Tue, 12 May 2015 14:47:56 +0100 -Subject: [PATCH 059/205] rpi-ft5406: Add touchscreen driver for pi LCD display +Subject: [PATCH 059/207] rpi-ft5406: Add touchscreen driver for pi LCD display Fix driver detection failure Check that the buffer response is non-zero meaning the touchscreen was detected @@ -108074,10 +108074,10 @@ index 30fb37fe175df604a738258a2a632bca3bfff33f..4a3d79d3b48eb483a4e4bf498f617515 RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f, -From 36a3450c65a1bb45b908fe0da9418a099c880ace Mon Sep 17 00:00:00 2001 +From 1cf92ae7aad19ea95e4506e67c32f274415f088b Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 28 Nov 2016 16:50:04 +0000 -Subject: [PATCH 060/205] Improve __copy_to_user and __copy_from_user +Subject: [PATCH 060/207] Improve __copy_to_user and __copy_from_user performance Provide a __copy_from_user that uses memcpy. On BCM2708, use @@ -109652,10 +109652,10 @@ index 333dc3c2e5ffbb2c5ab8fcfb6115b6162643cf20..46b787a6474ffa857da9b663948863ec bool "Broadcom BCM63xx DSL SoC" depends on ARCH_MULTI_V7 -From e138b9fd272fa5efffc546cccf56d75d50bdd380 Mon Sep 17 00:00:00 2001 +From 3f7866a141f04d33bc54b926e210a93387646c20 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 25 Jun 2015 12:16:11 +0100 -Subject: [PATCH 061/205] gpio-poweroff: Allow it to work on Raspberry Pi +Subject: [PATCH 061/207] gpio-poweroff: Allow it to work on Raspberry Pi The Raspberry Pi firmware manages the power-down and reboot process. To do this it installs a pm_power_off handler, causing @@ -109690,10 +109690,10 @@ index be3d81ff51cc3f510d85e4eed7a52960e51e7bc1..a030ae9fb1fca325061c093696e82186 "%s: pm_power_off function already registered", __func__); -From a53c8c0bd1cdc169608542a4935da4d8d3395868 Mon Sep 17 00:00:00 2001 +From fc9d3ee754a9ddd85e7d72efeb99842b7733bd00 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 14 Jul 2015 14:32:47 +0100 -Subject: [PATCH 062/205] mfd: Add Raspberry Pi Sense HAT core driver +Subject: [PATCH 062/207] mfd: Add Raspberry Pi Sense HAT core driver --- drivers/input/joystick/Kconfig | 8 + @@ -110558,10 +110558,10 @@ index 0000000000000000000000000000000000000000..56196dc2af10e464a1e3f98b028dca1c + +#endif -From 9cbc38ee1074b37c78d551fc381086c4d81ab190 Mon Sep 17 00:00:00 2001 +From f93d1061ef07b8cbe7e385cce7f122a1a387cbcc Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Fri, 22 Nov 2013 19:19:08 +0100 -Subject: [PATCH 063/205] ASoC: Add support for HifiBerry DAC +Subject: [PATCH 063/207] ASoC: Add support for HifiBerry DAC This adds a machine driver for the HifiBerry DAC. It is a sound card that can @@ -110736,10 +110736,10 @@ index 0000000000000000000000000000000000000000..45f2b770ad9e67728ca599a7445d6ae9 +MODULE_DESCRIPTION("ASoC Driver for HifiBerry DAC"); +MODULE_LICENSE("GPL v2"); -From 9772ec482c8a91c9e406df8e7e2548f0117336fd Mon Sep 17 00:00:00 2001 +From cd3e567a42daa711f7eb54e8b1d3ec382c04789f Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Mon, 25 Jan 2016 15:48:59 +0000 -Subject: [PATCH 064/205] ASoC: Add support for Rpi-DAC +Subject: [PATCH 064/207] ASoC: Add support for Rpi-DAC --- sound/soc/bcm/Kconfig | 7 +++ @@ -111023,10 +111023,10 @@ index 0000000000000000000000000000000000000000..afe1b419582aa40c4b2729d242bb13cd +MODULE_AUTHOR("Florian Meier "); +MODULE_LICENSE("GPL v2"); -From 0c3f035a70a8d60c296e566c7c7e0a505569f579 Mon Sep 17 00:00:00 2001 +From e62533efee7363a3445e0a3bfc226232f43d1ab4 Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Wed, 15 Jan 2014 21:41:23 +0100 -Subject: [PATCH 065/205] ASoC: wm8804: Implement MCLK configuration options, +Subject: [PATCH 065/207] ASoC: wm8804: Implement MCLK configuration options, add 32bit support WM8804 can run with PLL frequencies of 256xfs and 128xfs for most sample rates. At 192kHz only 128xfs is supported. The existing driver selects 128xfs automatically for some lower samples rates. By using an @@ -111075,10 +111075,10 @@ index af95d648265b3e92e345101542b332aee35191d4..513f56ba132929662802d15cdc653af3 .component_driver = { .dapm_widgets = wm8804_dapm_widgets, -From 4907c30093b27c97f4485fe9be38b523e6d815bd Mon Sep 17 00:00:00 2001 +From 3ef0c5216cf1862c7df73c0d430eed6b86954428 Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Wed, 15 Jan 2014 21:42:08 +0100 -Subject: [PATCH 066/205] ASoC: BCM:Add support for HiFiBerry Digi. Driver is +Subject: [PATCH 066/207] ASoC: BCM:Add support for HiFiBerry Digi. Driver is based on the patched WM8804 driver. Signed-off-by: Daniel Matuschek @@ -111422,10 +111422,10 @@ index 0000000000000000000000000000000000000000..19dc953b7227ba86123fc7a2ba654499 +MODULE_DESCRIPTION("ASoC Driver for HifiBerry Digi"); +MODULE_LICENSE("GPL v2"); -From 4bd8e0800da50bd688d5787601e442070d40a809 Mon Sep 17 00:00:00 2001 +From 2312bac6bf09ea4ab9b2acc4022e73ff8b342304 Mon Sep 17 00:00:00 2001 From: Gordon Garrity Date: Sat, 8 Mar 2014 16:56:57 +0000 -Subject: [PATCH 067/205] Add IQaudIO Sound Card support for Raspberry Pi +Subject: [PATCH 067/207] Add IQaudIO Sound Card support for Raspberry Pi Set a limit of 0dB on Digital Volume Control @@ -111755,10 +111755,10 @@ index 0000000000000000000000000000000000000000..4e8e6dec14bcf4a1ff286c43742d4097 +MODULE_DESCRIPTION("ASoC Driver for IQAudio DAC"); +MODULE_LICENSE("GPL v2"); -From d2a86da7a79aa531e71456cf77e86a6315b88003 Mon Sep 17 00:00:00 2001 +From a5da9f53a82464a7930bea0ee4498950763f3b22 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 25 Jul 2016 17:06:50 +0100 -Subject: [PATCH 068/205] iqaudio-dac: Compile fix - untested +Subject: [PATCH 068/207] iqaudio-dac: Compile fix - untested --- sound/soc/bcm/iqaudio-dac.c | 6 +++++- @@ -111782,10 +111782,10 @@ index 4e8e6dec14bcf4a1ff286c43742d4097249d6777..aa15bc4b49ca95edec905fddd8fd0a6d if (dapm->dev != codec_dai->dev) return 0; -From 9f4886062969d6390ff62b8f9db2721318310ee2 Mon Sep 17 00:00:00 2001 +From eacf5dfdcc9f8e99ea19bfeddf517a5dccf1d6a3 Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Mon, 4 Aug 2014 10:06:56 +0200 -Subject: [PATCH 069/205] Added support for HiFiBerry DAC+ +Subject: [PATCH 069/207] Added support for HiFiBerry DAC+ The driver is based on the HiFiBerry DAC driver. However HiFiBerry DAC+ uses a different codec chip (PCM5122), therefore a new driver is necessary. @@ -112415,10 +112415,10 @@ index 72b19e62f6267698aea45d2410d616d91c1825cb..c6839ef6e16754ed9de2698507b8986a dev_err(dev, "No LRCLK?\n"); return -EINVAL; -From 4bb23e6d2f10cfa66b156479d9f1cf4853ff9ae2 Mon Sep 17 00:00:00 2001 +From 822d2207b959b65731fa5f683abb96a4a1a7f3b1 Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Mon, 4 Aug 2014 11:09:58 +0200 -Subject: [PATCH 070/205] Added driver for HiFiBerry Amp amplifier add-on board +Subject: [PATCH 070/207] Added driver for HiFiBerry Amp amplifier add-on board The driver contains a low-level hardware driver for the TAS5713 and the drivers for the Raspberry Pi I2S subsystem. @@ -113253,10 +113253,10 @@ index 0000000000000000000000000000000000000000..8f019e04898754d2f87e9630137be9e8 + +#endif /* _TAS5713_H */ -From 591f148c7ce1c80eb98d5c891e9b17ba4a1318f3 Mon Sep 17 00:00:00 2001 +From 55f070954f6aada95b4d73a9ee94a830a49d0b9a Mon Sep 17 00:00:00 2001 From: Ryan Coe Date: Sat, 31 Jan 2015 18:25:49 -0700 -Subject: [PATCH 071/205] Update ds1307 driver for device-tree support +Subject: [PATCH 071/207] Update ds1307 driver for device-tree support Signed-off-by: Ryan Coe --- @@ -113283,10 +113283,10 @@ index 4ad97be480430babc3321075f2739114eaad8f04..2ac1c265dc9cea56a5949eb537949a1f .driver = { .name = "rtc-ds1307", -From f0b2ded01033dea7edbebdf019c18ddb96c86811 Mon Sep 17 00:00:00 2001 +From a7da0192208f19e2be8a5b337dae29b049a776b2 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Wed, 25 Mar 2015 09:26:17 +0100 -Subject: [PATCH 072/205] Add driver for rpi-proto +Subject: [PATCH 072/207] Add driver for rpi-proto Forward port of 3.10.x driver from https://github.com/koalo We are using a custom board and would like to use rpi 3.18.x @@ -113502,10 +113502,10 @@ index 0000000000000000000000000000000000000000..9db678e885efd63d84d60a098a84ed67 +MODULE_DESCRIPTION("ASoC Driver for Raspberry Pi connected to PROTO board (WM8731)"); +MODULE_LICENSE("GPL"); -From ebdb4c3382c5d2d155335a30143562a6248eccde Mon Sep 17 00:00:00 2001 +From 5f88ad2a09f0ccd0bdbc34a5fd53e0ef52a1ba9e Mon Sep 17 00:00:00 2001 From: Jan Grulich Date: Mon, 24 Aug 2015 16:03:47 +0100 -Subject: [PATCH 073/205] RaspiDAC3 support +Subject: [PATCH 073/207] RaspiDAC3 support Signed-off-by: Jan Grulich @@ -113748,10 +113748,10 @@ index 0000000000000000000000000000000000000000..dd9eeea2af0382307f437e6db09d1546 +MODULE_DESCRIPTION("ASoC Driver for RaspiDAC Rev.3x"); +MODULE_LICENSE("GPL v2"); -From 89d9d5733bdcae14793cb1467c13bb69abdc277f Mon Sep 17 00:00:00 2001 +From e8d17f1fefd19d40fba602e56511ca5aaf66ae12 Mon Sep 17 00:00:00 2001 From: Aaron Shaw Date: Thu, 7 Apr 2016 21:26:21 +0100 -Subject: [PATCH 074/205] Add Support for JustBoom Audio boards +Subject: [PATCH 074/207] Add Support for JustBoom Audio boards justboom-dac: Adjust for ALSA API change @@ -114205,10 +114205,10 @@ index 0000000000000000000000000000000000000000..91acb666380faa3c0deb2230f8a0f8bb +MODULE_DESCRIPTION("ASoC Driver for JustBoom PI Digi HAT Sound Card"); +MODULE_LICENSE("GPL v2"); -From 86561c96661655b381e4e1556616234ced342768 Mon Sep 17 00:00:00 2001 +From 48f292608909b6b1a6a438b4b224f25a4edecbf1 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 3 May 2016 22:10:59 -0400 -Subject: [PATCH 075/205] ARM: adau1977-adc: Add basic machine driver for +Subject: [PATCH 075/207] ARM: adau1977-adc: Add basic machine driver for adau1977 codec driver. This commit adds basic support for the codec usage including: Device tree overlay, @@ -114390,10 +114390,10 @@ index 0000000000000000000000000000000000000000..6e2ee027926ee63c89222f75ceb89e3d +MODULE_DESCRIPTION("ASoC Driver for ADAU1977 ADC"); +MODULE_LICENSE("GPL v2"); -From a780203c09b42a6b2bc763eb123dbedadc3bafc4 Mon Sep 17 00:00:00 2001 +From 57212d3a322d706c094566ce0263dfeeb9b56593 Mon Sep 17 00:00:00 2001 From: Matt Flax Date: Mon, 16 May 2016 21:36:31 +1000 -Subject: [PATCH 076/205] New AudioInjector.net Pi soundcard with low jitter +Subject: [PATCH 076/207] New AudioInjector.net Pi soundcard with low jitter audio in and out. Contains the sound/soc/bcm ALSA machine driver and necessary alterations to the Kconfig and Makefile. @@ -114644,10 +114644,10 @@ index 0000000000000000000000000000000000000000..ef54e0f07ea03f59e9957b5d98f3e7fd +MODULE_ALIAS("platform:audioinjector-pi-soundcard"); + -From 27e5b418cac8aa6274f4d480d4dbedf025d44fa9 Mon Sep 17 00:00:00 2001 +From 7d07976860e6d53fe6365f4611e2e61a4688c56f Mon Sep 17 00:00:00 2001 From: DigitalDreamtime Date: Thu, 30 Jun 2016 18:38:42 +0100 -Subject: [PATCH 077/205] Add IQAudIO Digi WM8804 board support +Subject: [PATCH 077/207] Add IQAudIO Digi WM8804 board support Support IQAudIO Digi board with iqaudio_digi machine driver and iqaudio-digi-wm8804-audio overlay. @@ -114947,10 +114947,10 @@ index 0000000000000000000000000000000000000000..9b6e829bcb5b1762a853775e78163196 +MODULE_DESCRIPTION("ASoC Driver for IQAudIO WM8804 Digi"); +MODULE_LICENSE("GPL v2"); -From bba08c2c3f50e78a0c3435c902da2dd6f3bc1e66 Mon Sep 17 00:00:00 2001 +From 984d86a15c517a33e027e1a8fa24883d9c615447 Mon Sep 17 00:00:00 2001 From: escalator2015 Date: Tue, 24 May 2016 16:20:09 +0100 -Subject: [PATCH 078/205] New driver for RRA DigiDAC1 soundcard using WM8741 + +Subject: [PATCH 078/207] New driver for RRA DigiDAC1 soundcard using WM8741 + WM8804 --- @@ -115423,10 +115423,10 @@ index 0000000000000000000000000000000000000000..446796e7e4c14a7d95b2f2a01211d9a0 +MODULE_DESCRIPTION("ASoC Driver for RRA DigiDAC1"); +MODULE_LICENSE("GPL v2"); -From 435fc7c959e710fa5cb7a60cb96c5fad70d9dcb7 Mon Sep 17 00:00:00 2001 +From 643f0e1d19aaeea2573d42454e8dc2161d3492ee Mon Sep 17 00:00:00 2001 From: DigitalDreamtime Date: Sat, 2 Jul 2016 16:26:19 +0100 -Subject: [PATCH 079/205] Add support for Dion Audio LOCO DAC-AMP HAT +Subject: [PATCH 079/207] Add support for Dion Audio LOCO DAC-AMP HAT Using dedicated machine driver and pcm5102a codec driver. @@ -115599,10 +115599,10 @@ index 0000000000000000000000000000000000000000..89e65317512bc774453ac8d0d5b0ff98 +MODULE_DESCRIPTION("ASoC Driver for DionAudio LOCO"); +MODULE_LICENSE("GPL v2"); -From c69093cb41abf142977a1cf13b1b8dcc0079dfd3 Mon Sep 17 00:00:00 2001 +From 59c9bca85041c674aaa8bdaef3fbf0cf8f1a9794 Mon Sep 17 00:00:00 2001 From: Clive Messer Date: Mon, 19 Sep 2016 14:01:04 +0100 -Subject: [PATCH 080/205] Allo Piano DAC boards: Initial 2 channel (stereo) +Subject: [PATCH 080/207] Allo Piano DAC boards: Initial 2 channel (stereo) support (#1645) Add initial 2 channel (stereo) support for Allo Piano DAC (2.0/2.1) boards, @@ -115809,10 +115809,10 @@ index 0000000000000000000000000000000000000000..8e8e62e5a36a279b425ed4655cfbac99 +MODULE_DESCRIPTION("ALSA ASoC Machine Driver for Allo Piano DAC"); +MODULE_LICENSE("GPL v2"); -From 53d6282751283889579eed544ae77360d6835286 Mon Sep 17 00:00:00 2001 +From 6d4c1945df2bd9f3841056cddb6e231a00ede202 Mon Sep 17 00:00:00 2001 From: gtrainavicius Date: Sun, 23 Oct 2016 12:06:53 +0300 -Subject: [PATCH 081/205] Support for Blokas Labs pisound board +Subject: [PATCH 081/207] Support for Blokas Labs pisound board Pisound dynamic overlay (#1760) @@ -116989,10 +116989,10 @@ index 0000000000000000000000000000000000000000..4b8545487d06e4ea70073a5d063fb231 +MODULE_DESCRIPTION("ASoC Driver for pisound, http://blokas.io/pisound"); +MODULE_LICENSE("GPL v2"); -From 8e740956c01af7265d2a8767a016a4cf9e57876e Mon Sep 17 00:00:00 2001 +From a93017e330080a37910d2dc11d02b5c885f0b121 Mon Sep 17 00:00:00 2001 From: P33M Date: Wed, 21 Oct 2015 14:55:21 +0100 -Subject: [PATCH 082/205] rpi_display: add backlight driver and overlay +Subject: [PATCH 082/207] rpi_display: add backlight driver and overlay Add a mailbox-driven backlight controller for the Raspberry Pi DSI touchscreen display. Requires updated GPU firmware to recognise the @@ -117161,10 +117161,10 @@ index 0000000000000000000000000000000000000000..14a0d9b037395497c1fdae2961feccd5 +MODULE_DESCRIPTION("Raspberry Pi mailbox based Backlight Driver"); +MODULE_LICENSE("GPL"); -From 3d74769161a89c38af18836cd61c39336073391a Mon Sep 17 00:00:00 2001 +From 07264b015ef09aa27e1685d4cda6390244b4e6d0 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 23 Feb 2016 19:56:04 +0000 -Subject: [PATCH 083/205] bcm2835-virtgpio: Virtual GPIO driver +Subject: [PATCH 083/207] bcm2835-virtgpio: Virtual GPIO driver Add a virtual GPIO driver that uses the firmware mailbox interface to request that the VPU toggles LEDs. @@ -117438,10 +117438,10 @@ index 4a3d79d3b48eb483a4e4bf498f617515e3ad158f..5f34e1257117fb48013c9926a8a223d6 RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f, -From 96dd99c8e9f4ea6711bccf6ddd2159828e12d5a2 Mon Sep 17 00:00:00 2001 +From 16005503b07ae9367d848466cb7a0af7b75886b5 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 23 Feb 2016 17:26:48 +0000 -Subject: [PATCH 084/205] amba_pl011: Don't use DT aliases for numbering +Subject: [PATCH 084/207] amba_pl011: Don't use DT aliases for numbering The pl011 driver looks for DT aliases of the form "serial", and if found uses as the device ID. This can cause @@ -117470,10 +117470,10 @@ index d4171d71a258f2696ab2ab2109376ee5a516bfba..6beb6233a0b6132b933cf8d85d8501dc uap->old_cr = 0; uap->port.dev = dev; -From 73b7b540c10ff8f3e258e7f57bc563a08dc82980 Mon Sep 17 00:00:00 2001 +From c9eb72860b890a880c8a53af717f0381af70d0bf Mon Sep 17 00:00:00 2001 From: Pantelis Antoniou Date: Wed, 3 Dec 2014 13:23:28 +0200 -Subject: [PATCH 085/205] OF: DT-Overlay configfs interface +Subject: [PATCH 085/207] OF: DT-Overlay configfs interface This is a port of Pantelis Antoniou's v3 port that makes use of the new upstreamed configfs support for binary attributes. @@ -117905,10 +117905,10 @@ index 0000000000000000000000000000000000000000..0037e6868a6cda8706c88194c6a4454b +} +late_initcall(of_cfs_init); -From d93fed4764d1de72402a0841cfb5b2d68242676c Mon Sep 17 00:00:00 2001 +From fc32f6cc90b78b32d0ffe409574bb637d66e9120 Mon Sep 17 00:00:00 2001 From: Cheong2K Date: Fri, 26 Feb 2016 18:20:10 +0800 -Subject: [PATCH 086/205] brcm: adds support for BCM43341 wifi +Subject: [PATCH 086/207] brcm: adds support for BCM43341 wifi brcmfmac: Disable power management @@ -118059,10 +118059,10 @@ index d2219885071f6d718f0f26320d580c66adc26e36..d13826095c09f5b4037625371fe64890 BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, 43362), BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339), -From 87d510287389bae6818179724449c17875487b01 Mon Sep 17 00:00:00 2001 +From 71fa48bee3991a1f332f728dca63e4e4e554f696 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 17 Dec 2015 13:37:07 +0000 -Subject: [PATCH 087/205] hci_h5: Don't send conf_req when ACTIVE +Subject: [PATCH 087/207] hci_h5: Don't send conf_req when ACTIVE Without this patch, a modem and kernel can continuously bombard each other with conf_req and conf_rsp messages, in a demented game of tag. @@ -118085,10 +118085,10 @@ index 90d0456b67446bcc624fab4b1542c4eaf21531b1..f9adeac3bbba6418dcca298c55706356 if (H5_HDR_LEN(hdr) > 2) h5->tx_win = (data[2] & 0x07); -From efcdeaa6b728e548250837f915548c0cc2c47e07 Mon Sep 17 00:00:00 2001 +From 2d277ecc8b055dceb23f89197e5b248e9988a6ae Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 13 Apr 2015 17:16:29 +0100 -Subject: [PATCH 088/205] config: Add default configs +Subject: [PATCH 088/207] config: Add default configs --- arch/arm/configs/bcm2709_defconfig | 1297 +++++++++++++++++++++++++++++++++++ @@ -120715,10 +120715,10 @@ index 0000000000000000000000000000000000000000..8acee9f31202ec14f2933d92dd70831c +CONFIG_CRC_ITU_T=y +CONFIG_LIBCRC32C=y -From 644e30f04aece97e2e40a137db0d50059f4ac0c0 Mon Sep 17 00:00:00 2001 +From 216446501b5c80369ea4f39e095aaeefcdaa579f Mon Sep 17 00:00:00 2001 From: Michael Zoran Date: Wed, 24 Aug 2016 03:35:56 -0700 -Subject: [PATCH 089/205] Add arm64 configuration and device tree differences. +Subject: [PATCH 089/207] Add arm64 configuration and device tree differences. Disable MMC_BCM2835_SDHOST and MMC_BCM2835 since these drivers are crashing at the moment. @@ -122133,10 +122133,10 @@ index 0000000000000000000000000000000000000000..e6b09fafa27eed2b762e3d53b55041f7 +CONFIG_LIBCRC32C=y +CONFIG_BCM2835_VCHIQ=n -From 0cad2d18e2b6b9459523e0128594632e8356dba1 Mon Sep 17 00:00:00 2001 +From 922a918e547342265f1bbffb42b197ee50adb538 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 27 Dec 2016 22:13:42 +0000 -Subject: [PATCH 090/205] Revert "staging: vc04_services: remove +Subject: [PATCH 090/207] Revert "staging: vc04_services: remove vchiq_copy_from_user" This reverts commit 49bec49fd7f273ec114e2e533c1bb8f21a654aaf. @@ -122886,10 +122886,10 @@ index d9771394a041bbb55daacd7744ac57758ae198d1..7694627b925c743552b093ce51d15c2f * * Arguments: VCHI_HELD_MSG_T *message -From 50c63aaaf64670394dc13cfe14363913ff6cf401 Mon Sep 17 00:00:00 2001 +From aa059423064b4c6e34a5fae1ea22a93c7dc5543b Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 23 Mar 2016 14:16:25 +0000 -Subject: [PATCH 091/205] vchiq_arm: Access the dequeue_pending flag locked +Subject: [PATCH 091/207] vchiq_arm: Access the dequeue_pending flag locked Reading through this code looking for another problem (now found in userland) the use of dequeue_pending outside a lock didn't seem safe. @@ -122947,10 +122947,10 @@ index 42998155eb4d7de8e49cc1ca82d84a430562a8da..74f1569097c7dd120cc68fb8d09d8c3d return add_completion(instance, reason, header, user_service, -From 4b4ebbf1bcb63736f5eb4d882b414e5e6f6fc98e Mon Sep 17 00:00:00 2001 +From 55e13746b1fc96705532d6a55997937d53fe58cc Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 23 Mar 2016 20:53:47 +0000 -Subject: [PATCH 092/205] vchiq_arm: Service callbacks must not fail +Subject: [PATCH 092/207] vchiq_arm: Service callbacks must not fail Service callbacks are not allowed to return an error. The internal callback that delivers events and messages to user tasks does not enqueue them if @@ -122976,10 +122976,10 @@ index 74f1569097c7dd120cc68fb8d09d8c3d63d56977..3ba6485f0c7b32de9f2aa75164e8b1b9 DEBUG_TRACE(SERVICE_CALLBACK_LINE); } -From 068a3fa44b5198495792a77933e8645e5f5cfdfe Mon Sep 17 00:00:00 2001 +From a7c375a0866275ae662771e807939fedc2973b69 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 21 Apr 2016 13:49:32 +0100 -Subject: [PATCH 093/205] vchiq_arm: Add completion records under the mutex +Subject: [PATCH 093/207] vchiq_arm: Add completion records under the mutex An issue was observed when flushing openmax components which generate a large number of messages returning @@ -123042,10 +123042,10 @@ index 3ba6485f0c7b32de9f2aa75164e8b1b901aa74ea..07d8eadd2aa2dc997db13c80dc303673 return VCHIQ_SUCCESS; -From 8bbf668306772effafb0bf3231a472398354c2ce Mon Sep 17 00:00:00 2001 +From 5089de7bc2d4418e2211a4dc01f70a81db591c54 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 20 Jun 2016 13:51:44 +0100 -Subject: [PATCH 094/205] vchiq_arm: Avoid use of mutex in add_completion +Subject: [PATCH 094/207] vchiq_arm: Avoid use of mutex in add_completion Claiming the completion_mutex within add_completion did prevent some messages appearing twice, but provokes a deadlock caused by vcsm using @@ -123239,10 +123239,10 @@ index c5b06cc4ca53135ec9491116ca79beaa98f57bcc..d6757ee263fb61a689c0d38c0dbb65c5 up(&state->slot_available_event); } -From f385495282bad46792b9d65907004607b154288d Mon Sep 17 00:00:00 2001 +From 39c29d827a824141f90968e412926b733cdbdf79 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 14 Sep 2016 09:18:09 +0100 -Subject: [PATCH 095/205] raspberrypi-firmware: Define the MBOX channel in the +Subject: [PATCH 095/207] raspberrypi-firmware: Define the MBOX channel in the header. Signed-off-by: Eric Anholt @@ -123264,10 +123264,10 @@ index 5f34e1257117fb48013c9926a8a223d64a598ab7..7f0da0727422c690947e46e891a754de enum rpi_firmware_property_status { -From 696fa19661346de074dce8e24953988308429b23 Mon Sep 17 00:00:00 2001 +From a574835e20d276fdc643e403205d730f5bf9b813 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 14 Sep 2016 08:39:33 +0100 -Subject: [PATCH 096/205] drm/vc4: Add a mode for using the closed firmware for +Subject: [PATCH 096/207] drm/vc4: Add a mode for using the closed firmware for display. Signed-off-by: Eric Anholt @@ -124034,10 +124034,10 @@ index 0000000000000000000000000000000000000000..d18a1dae51a2275846c9826b5bf1ba57 + }, +}; -From a39f80334c05f02fce1664d3326119f2f8d8d5e7 Mon Sep 17 00:00:00 2001 +From 030fd941af2fdf693e5bff2e21e1e4677792f524 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Tue, 1 Nov 2016 15:15:41 +0100 -Subject: [PATCH 097/205] i2c: bcm2835: Add debug support +Subject: [PATCH 097/207] i2c: bcm2835: Add debug support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -124226,10 +124226,10 @@ index cd07a69e2e9355540442785f95e90823b05c9d10..47167f403cc8329bd811b47c7011c299 if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) return -EREMOTEIO; -From 6c2a6f1028bf676ef0897ed67dd0539aba35bc04 Mon Sep 17 00:00:00 2001 +From 76cae8dbdcb81e36e4099b6a12b904ecc2df0d4f Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 14 Sep 2016 09:16:19 +0100 -Subject: [PATCH 098/205] raspberrypi-firmware: Export the general transaction +Subject: [PATCH 098/207] raspberrypi-firmware: Export the general transaction function. The vc4-firmware-kms module is going to be doing the MBOX FB call. @@ -124273,10 +124273,10 @@ index 7f0da0727422c690947e46e891a754de13dc1fea..280791fb9656901392ce67e44cb742c9 #endif /* __SOC_RASPBERRY_FIRMWARE_H__ */ -From a3bfb87c5ecb676a2b8f31377c8d2113a7f6f368 Mon Sep 17 00:00:00 2001 +From f015d743a284fc010ff5126d07143de9985e8cff Mon Sep 17 00:00:00 2001 From: Alex Tucker Date: Tue, 13 Dec 2016 19:50:18 +0000 -Subject: [PATCH 099/205] Add support for Silicon Labs Si7013/20/21 +Subject: [PATCH 099/207] Add support for Silicon Labs Si7013/20/21 humidity/temperature sensor. --- @@ -124351,10 +124351,10 @@ index f6d134c095af2398fc55ae7d2b0e86456c30627c..31bda8da4cb6a56bfe493a81b9189009 }; }; -From 55b11bec6fac9fb7d5d41d41283e84cc75967867 Mon Sep 17 00:00:00 2001 +From 0fc169ddc533660d69d4827091fbd6231777784f Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 3 Jan 2017 21:27:46 +0000 -Subject: [PATCH 100/205] Document the si7020 option +Subject: [PATCH 100/207] Document the si7020 option --- arch/arm/boot/dts/overlays/README | 3 +++ @@ -124375,10 +124375,10 @@ index 81d991803be335e5a1bc3bb0a8c7a2c9f5c392bd..e8fa4ccb44c34a20485c4e6155467af9 Name: i2c0-bcm2708 Info: Enable the i2c_bcm2708 driver for the i2c0 bus. Not all pin combinations -From c698b16a276178c8730c425e84732d9043e748ca Mon Sep 17 00:00:00 2001 +From 9ea0a3f3dd53ef03deb7b2c67acf6fc4a987d1f6 Mon Sep 17 00:00:00 2001 From: Giedrius Trainavicius Date: Thu, 5 Jan 2017 02:38:16 +0200 -Subject: [PATCH 101/205] pisound improvements: +Subject: [PATCH 101/207] pisound improvements: * Added a writable sysfs object to enable scripts / user space software to blink MIDI activity LEDs for variable duration. @@ -124672,10 +124672,10 @@ index 4b8545487d06e4ea70073a5d063fb2310b3b94d0..ba70734b89e61a11201657406223f0b3 }; -From 27376030ff6d6ccce2803f9bfb8bb562cf2e5666 Mon Sep 17 00:00:00 2001 +From 0048949320881bf54949eb5a49950b94d3f9f5f4 Mon Sep 17 00:00:00 2001 From: Aaron Shaw Date: Tue, 10 Jan 2017 16:05:41 +0000 -Subject: [PATCH 102/205] Add driver_name property +Subject: [PATCH 102/207] Add driver_name property Add driver name property for use with 5.1 passthrough audio in LibreElec and other Kodi based OSs --- @@ -124695,10 +124695,10 @@ index 8fd50dbe681508a2cfe8fdde1c9fedbe9a507fa7..05a224ec712d06b8b7587ab6b8bb562d .dai_link = snd_rpi_justboom_dac_dai, .num_links = ARRAY_SIZE(snd_rpi_justboom_dac_dai), -From 525a8fb0e65f81a7335c54da148f5a05506f7625 Mon Sep 17 00:00:00 2001 +From f58ad492c10dea2fc84408365449d2caccf1cb21 Mon Sep 17 00:00:00 2001 From: Aaron Shaw Date: Tue, 10 Jan 2017 16:11:04 +0000 -Subject: [PATCH 103/205] Add driver_name paramater +Subject: [PATCH 103/207] Add driver_name paramater Add driver_name parameter for use with 5.1 passthrough audio in LibreElec and other Kodi OSs --- @@ -124718,10 +124718,10 @@ index 91acb666380faa3c0deb2230f8a0f8bbec59417b..abfdc5c4dd5811e6847bddda4921abe3 .dai_link = snd_rpi_justboom_digi_dai, .num_links = ARRAY_SIZE(snd_rpi_justboom_digi_dai), -From 2dbd2e05fc268252b2cf302df8e7e0ca7021989b Mon Sep 17 00:00:00 2001 +From c75a4865885baa575d778bdf3ea01bacc12abf7b Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 11 Jan 2017 13:01:21 +0000 -Subject: [PATCH 104/205] BCM270X_DT: Add pi3-disable-wifi overlay +Subject: [PATCH 104/207] BCM270X_DT: Add pi3-disable-wifi overlay pi3-disable-wifi is a minimal overlay to disable the onboard WiFi. @@ -124782,10 +124782,10 @@ index 0000000000000000000000000000000000000000..017199554bf2f4e381efcc7bb71e750c + }; +}; -From 91140a2e2bae65c49ec0eecb86923fbfffc8b471 Mon Sep 17 00:00:00 2001 +From 7158ab7a355c58a9c55fe6729d71bc2f83ef14ab Mon Sep 17 00:00:00 2001 From: Electron752 Date: Thu, 12 Jan 2017 07:07:08 -0800 -Subject: [PATCH 105/205] ARM64: Make it work again on 4.9 (#1790) +Subject: [PATCH 105/207] ARM64: Make it work again on 4.9 (#1790) * Invoke the dtc compiler with the same options used in arm mode. * ARM64 now uses the bcm2835 platform just like ARM32. @@ -125189,10 +125189,10 @@ index e6b09fafa27eed2b762e3d53b55041f793683d27..c7e891d72969a388d9b135a36dbfc9c9 CONFIG_LIBCRC32C=y -CONFIG_BCM2835_VCHIQ=n -From e97d3f98da225eaad75dea27e93e8ad4459dc93c Mon Sep 17 00:00:00 2001 +From b24e1af0e78164d6cc2b5e08d322675117875be4 Mon Sep 17 00:00:00 2001 From: Michael Zoran Date: Thu, 12 Jan 2017 18:56:54 -0800 -Subject: [PATCH 106/205] ARM64: Fix bad cast in vc04_services +Subject: [PATCH 106/207] ARM64: Fix bad cast in vc04_services The function vchiq_copy_from_user contains a non-portable cast to uint32_t. Convert this to a cast to unsigned long @@ -125217,10 +125217,10 @@ index 706e7f936c1a97352f7ef3d3fbd3b4a92943165d..c2108dec3096fffd68261f0eb29a37d3 } else { memcpy(dst, src, size); -From c6f9dad3f09532adea67b843e1fdd24591754361 Mon Sep 17 00:00:00 2001 +From 9a53d4f1c0d7283675a8c4e62925db0a3167e9ab Mon Sep 17 00:00:00 2001 From: Michael Zoran Date: Thu, 12 Jan 2017 19:05:46 -0800 -Subject: [PATCH 107/205] ARM64/SND_BCM2835: Port it to arm64. +Subject: [PATCH 107/207] ARM64/SND_BCM2835: Port it to arm64. In the messages sent to VCHIQ, SND_BCM2835 passes a callback and a context into two 32 bit pointers. Since this @@ -125317,10 +125317,10 @@ index af3e6eb690113fc32ce9e06bd2f0f294da7a7f00..ede6154bc09d38469a82008174d0e357 // Message header for all messages in HOST->VC direction -From 3e06a71428002226afacc3bb41f5026acb0e7c45 Mon Sep 17 00:00:00 2001 +From 673bd5e362d59fed523bca3b191c80d60fc572a8 Mon Sep 17 00:00:00 2001 From: Michael Zoran Date: Thu, 12 Jan 2017 19:10:07 -0800 -Subject: [PATCH 108/205] ARM64: Enable HDMI audio and vc04_services in +Subject: [PATCH 108/207] ARM64: Enable HDMI audio and vc04_services in bcmrpi3_defconfig Signed-off-by: Michael Zoran @@ -125349,10 +125349,10 @@ index c7e891d72969a388d9b135a36dbfc9c9cb609bf8..4b90f9b64abe9f089ba56b13d5a00de3 CONFIG_BCM2835_MBOX=y # CONFIG_IOMMU_SUPPORT is not set -From 6740d51939d9e08d13682f54ca697850682a3b58 Mon Sep 17 00:00:00 2001 +From 8ec1c7f5de4c210a4ca2cba22f492e13e01897d9 Mon Sep 17 00:00:00 2001 From: Michael Zoran Date: Thu, 12 Jan 2017 19:14:03 -0800 -Subject: [PATCH 109/205] ARM64: Run bcmrpi3_defconfig through savedefconfig. +Subject: [PATCH 109/207] ARM64: Run bcmrpi3_defconfig through savedefconfig. Signed-off-by: Michael Zoran --- @@ -125397,10 +125397,10 @@ index 4b90f9b64abe9f089ba56b13d5a00de33343bfb9..dac962ca1634662ce7d966f1ffb53b5b CONFIG_FB_TFT_AGM1264K_FL=m CONFIG_FB_TFT_BD663474=m -From 2f29500ecd02eb42cbeb09b8f0a2fa72aac8dda8 Mon Sep 17 00:00:00 2001 +From 520539d8a9a12b5838f3ebf1ec5eb27809b8a278 Mon Sep 17 00:00:00 2001 From: Electron752 Date: Sat, 14 Jan 2017 02:54:26 -0800 -Subject: [PATCH 110/205] ARM64: Enable Kernel Address Space Randomization +Subject: [PATCH 110/207] ARM64: Enable Kernel Address Space Randomization (#1792) Randomization allows the mapping between virtual addresses and physical @@ -125432,10 +125432,10 @@ index dac962ca1634662ce7d966f1ffb53b5bfa27c506..aae33b4b3c3e736ea7cd3ca242158ad6 CONFIG_BINFMT_MISC=y CONFIG_COMPAT=y -From a90c5355ad0311c020d235f1f8951f8ca96c47a8 Mon Sep 17 00:00:00 2001 +From 983aa0b7e73664a13010069ff54801d47d0080cb Mon Sep 17 00:00:00 2001 From: Michael Zoran Date: Sun, 15 Jan 2017 07:31:59 -0800 -Subject: [PATCH 111/205] ARM64: Enable RTL8187/RTL8192CU wifi in build config +Subject: [PATCH 111/207] ARM64: Enable RTL8187/RTL8192CU wifi in build config These drivers build now, so they can be enabled back in the build configuration just like they are for @@ -125460,10 +125460,10 @@ index aae33b4b3c3e736ea7cd3ca242158ad6ba558aff..b7d762df19b85e369a32cd823dfd0621 CONFIG_ZD1211RW=m CONFIG_MAC80211_HWSIM=m -From 72109c487efb7dffc0435a89ae67d8290aba1ae8 Mon Sep 17 00:00:00 2001 +From 731c930dc0f60ec7764b075cdb13d30efdaf1466 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 16 Jan 2017 14:53:12 +0000 -Subject: [PATCH 112/205] BCM270X_DT: Add spi0-cs overlay +Subject: [PATCH 112/207] BCM270X_DT: Add spi0-cs overlay The spi0-cs overlay allows the software chip selectts to be modified using the cs0_pin and cs1_pin parameters. @@ -125551,10 +125551,10 @@ index 0000000000000000000000000000000000000000..7f79029d043c04d7496c7c3480450c69 + }; +}; -From c250fe68917c045c0278dc6ea3d7257f115ffd8c Mon Sep 17 00:00:00 2001 +From 4e42590b2362ce134a7b4d1c8d556ba7a8520e22 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 1 Jul 2016 22:09:24 +0100 -Subject: [PATCH 113/205] spi-bcm2835: Disable forced software CS +Subject: [PATCH 113/207] spi-bcm2835: Disable forced software CS Select software CS in bcm2708_common.dtsi, and disable the automatic conversion in the driver to allow hardware CS to be re-enabled with an @@ -125580,10 +125580,10 @@ index 9a44da19089717f02462c657840ae9f24fd942ba..b710a4d67b8ec8c8c18ce8efb6f270e7 i2c0: i2c@7e205000 { -From bb057983a110e1739a03d50083059782fb9200ec Mon Sep 17 00:00:00 2001 +From 9ba47884a61fcdbceabf3ee8231d2284d17468cb Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 17 Jan 2017 11:34:58 +0000 -Subject: [PATCH 114/205] BCM270X_DT: Enable UART0 on CM3 +Subject: [PATCH 114/207] BCM270X_DT: Enable UART0 on CM3 Signed-off-by: Phil Elwell --- @@ -125606,10 +125606,10 @@ index 41874c25a84226c0e4af92ec4059e0a571fe6123..3ba6e621856c288ae4694f758604619f sdhost_pins: sdhost_pins { brcm,pins = <48 49 50 51 52 53>; -From 054b61bb38c1da724fec77e1b03067e09b41ef27 Mon Sep 17 00:00:00 2001 +From 0e6924f059ae9c57a1d0025142f2a343147e0e83 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 17 Jan 2017 14:39:39 +0000 -Subject: [PATCH 115/205] config: Add CONFIG_MD_M25P80 and CONFIG_MD_SPI_NOR +Subject: [PATCH 115/207] config: Add CONFIG_MD_M25P80 and CONFIG_MD_SPI_NOR See: https://github.com/raspberrypi/linux/issues/1781 @@ -125714,10 +125714,10 @@ index 8acee9f31202ec14f2933d92dd70831cda8d7b51..aca8903da3156de11ba62afa64a06939 CONFIG_FB_TFT_AGM1264K_FL=m CONFIG_FB_TFT_BD663474=m -From e75edaa9687596b2af25851d01e134570fbfe5a0 Mon Sep 17 00:00:00 2001 +From eda3ed46a5260601b4e640b0ab942c0d03a35926 Mon Sep 17 00:00:00 2001 From: Michael Zoran Date: Sat, 14 Jan 2017 21:33:51 -0800 -Subject: [PATCH 116/205] ARM64/DWC_OTG: Port dwc_otg driver to ARM64 +Subject: [PATCH 116/207] ARM64/DWC_OTG: Port dwc_otg driver to ARM64 In ARM64, the FIQ mechanism used by this driver is not current implemented. As a workaround, reqular IRQ is used instead @@ -126060,10 +126060,10 @@ index 6b2c7d0c93f36a63863ff4b0ecc1f3eab77e058b..d7b700ff17821ad1944e36721fe6b2db /** The OS page size */ #define DWC_OS_PAGE_SIZE PAGE_SIZE -From 2f8e779297332362c7aa7794e2c51d10cb450f73 Mon Sep 17 00:00:00 2001 +From ec05c73664fdc9ab48d0aebef51af893faad16ab Mon Sep 17 00:00:00 2001 From: Michael Zoran Date: Sat, 14 Jan 2017 21:43:57 -0800 -Subject: [PATCH 117/205] ARM64: Round-Robin dispatch IRQs between CPUs. +Subject: [PATCH 117/207] ARM64: Round-Robin dispatch IRQs between CPUs. IRQ-CPU mapping is round robined on ARM64 to increase concurrency and allow multiple interrupts to be serviced @@ -126137,10 +126137,10 @@ index a8db33b50ad9ff83d284fa54fe4d3b65f859df0f..67dcac46cca72db4ebe2300eab04f0a8 .name = "bcm2836-gpu", .irq_mask = bcm2836_arm_irqchip_mask_gpu_irq, -From c25dfaf75092d68b6da74f68c648779932b68462 Mon Sep 17 00:00:00 2001 +From 9c400b8bd3e463fa6a884f4dbfc7cbc9ae8124d2 Mon Sep 17 00:00:00 2001 From: Michael Zoran Date: Sat, 14 Jan 2017 21:45:03 -0800 -Subject: [PATCH 118/205] ARM64: Enable DWC_OTG Driver In ARM64 Build +Subject: [PATCH 118/207] ARM64: Enable DWC_OTG Driver In ARM64 Build Config(bcmrpi3_defconfig) Signed-off-by: Michael Zoran @@ -126161,10 +126161,10 @@ index b7d762df19b85e369a32cd823dfd062145bdefa7..4d85c231c5ea0244e1b05fb4a5e3c8fd CONFIG_USB_STORAGE=y CONFIG_USB_STORAGE_REALTEK=m -From c5b8ec78a70520f6c97d5c10f1525734835e3f98 Mon Sep 17 00:00:00 2001 +From cc058cba312262cc64b18bd2f73538e4bb1bd3b8 Mon Sep 17 00:00:00 2001 From: Michael Zoran Date: Sat, 14 Jan 2017 21:46:04 -0800 -Subject: [PATCH 119/205] ARM64: Use dwc_otg driver by default for USB. +Subject: [PATCH 119/207] ARM64: Use dwc_otg driver by default for USB. If it breaks on anybody, they can use the standard device tree overlays to switch back to the dwc2 driver. @@ -126190,10 +126190,10 @@ index f6def5d7e5d622cf09e8f87332c7374fe28da08b..3e134a1208610b90e2d0fc22f03c6e9f -}; -#endif -From 9fc521b0625d3ccc2bead01c5b67280ae52a68eb Mon Sep 17 00:00:00 2001 +From 812e4f6bd584da5d463fa9fbda0a2b3eb4cbfb55 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 19 Jan 2017 11:18:55 +0000 -Subject: [PATCH 120/205] config: Add CONFIG_USB_DWC2 and CONFIG_USB_GADGET +Subject: [PATCH 120/207] config: Add CONFIG_USB_DWC2 and CONFIG_USB_GADGET The introduction of CM3 makes gadget mode on 2709 a useful option, so enable the building of the required modules. Note that these @@ -126226,10 +126226,10 @@ index c36f01d28097a513b32df092ce64a7d6b974e615..2e2b88fefdf367b2d9190ca227ea6eb3 CONFIG_MMC_BLOCK_MINORS=32 CONFIG_MMC_BCM2835=y -From 12c2ac8b3b41d55a017a69b8ee2c04cb37133731 Mon Sep 17 00:00:00 2001 +From 639718f27ad0da321a1b010888e3db776599f649 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 23 Jan 2017 17:36:50 +0000 -Subject: [PATCH 121/205] BCM270X_DT: Add reference to audio_pins to CM dtb +Subject: [PATCH 121/207] BCM270X_DT: Add reference to audio_pins to CM dtb The CM1 dtb contains an empty audio_pins node, but no reference to it. Adding the usual pinctrl reference from the audio node enables the @@ -126257,10 +126257,10 @@ index eb8662f0d222b4c0a9a2bcb8bccb13e86a0006b3..10be69972bd1440f574e35d515f3d6a0 hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>; }; -From 6a24f32ae2978d589a409cd5d12eda97d44e488c Mon Sep 17 00:00:00 2001 +From 7b3933b40417f08515cde6b696c7e3d8f5fd7d72 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 25 Jan 2017 11:30:38 +0000 -Subject: [PATCH 122/205] config: Add additional network scheduling modules +Subject: [PATCH 122/207] config: Add additional network scheduling modules --- arch/arm/configs/bcm2709_defconfig | 4 ++++ @@ -126312,10 +126312,10 @@ index aca8903da3156de11ba62afa64a0693900ee3611..c8c66751f263227e86cc21ad5b23861a CONFIG_NET_SCH_PLUG=m CONFIG_NET_CLS_BASIC=m -From b2d2339356c26475dfe08e3e2d1747b5201e7ff3 Mon Sep 17 00:00:00 2001 +From deead6e0367f78e991f4981a652d7aa58823ab87 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 16 Jan 2017 16:33:54 +0000 -Subject: [PATCH 123/205] config: Add CONFIG_TCP_CONG_BBR See: +Subject: [PATCH 123/207] config: Add CONFIG_TCP_CONG_BBR See: https://github.com/raspberrypi/linux/issues/1784 --- @@ -126350,10 +126350,10 @@ index c8c66751f263227e86cc21ad5b23861a88a636a6..e483bdb7aa869b212ef69ed779c6055e CONFIG_IPV6_ROUTER_PREF=y CONFIG_INET6_AH=m -From 0569bcfbe2dde6cc3f63e341491f14b6849ec3da Mon Sep 17 00:00:00 2001 +From 150abdca5f865aee6af5c1e4c92118aaa13da783 Mon Sep 17 00:00:00 2001 From: chris johnson Date: Sun, 22 Jan 2017 03:27:31 +0000 -Subject: [PATCH 124/205] ASoC: A simple-card overlay for ADAU7002 +Subject: [PATCH 124/207] ASoC: A simple-card overlay for ADAU7002 Usage: `dtoverlay=adau7002-simple` --- @@ -126451,10 +126451,10 @@ index 0000000000000000000000000000000000000000..e67e6625d7967abc92cf00cb604d4c12 + }; +}; -From e0ec5f0cebfbffe4105bb5c83251df2f4d7111c7 Mon Sep 17 00:00:00 2001 +From 0ea54a2e3edf2a4b94020388fcdd2408757e8153 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 25 Jan 2017 21:17:23 +0000 -Subject: [PATCH 125/205] config: Add SND_SOC_ADAU7002 codec module +Subject: [PATCH 125/207] config: Add SND_SOC_ADAU7002 codec module As there is now an overlay requiring it, build the codec module. @@ -126489,10 +126489,10 @@ index e483bdb7aa869b212ef69ed779c6055ef3b70e2a..1927b1671b6eced73e4b4d76352bb4b1 CONFIG_SND_SOC_WM8804_I2C=m CONFIG_SND_SIMPLE_CARD=m -From e6ce2230ec9cb41a1166abddf04202fa6e140174 Mon Sep 17 00:00:00 2001 +From ade7093076e39a103c12e748b3d04805131367f0 Mon Sep 17 00:00:00 2001 From: Scott Ellis Date: Fri, 27 Jan 2017 06:42:42 -0500 -Subject: [PATCH 126/205] Add overlay for mcp3008 adc (#1818) +Subject: [PATCH 126/207] Add overlay for mcp3008 adc (#1818) Some example usage: @@ -126778,10 +126778,10 @@ index 0000000000000000000000000000000000000000..06bf4264959c380d8a9f90f74e780397 + }; +}; -From e310829a8572def9671cae5fc9fbe23579ca8616 Mon Sep 17 00:00:00 2001 +From b3a18f253800f3d15513f42e215cd755ccf5d31b Mon Sep 17 00:00:00 2001 From: JamesH65 Date: Mon, 6 Feb 2017 15:24:47 +0000 -Subject: [PATCH 127/205] gpio_mem: Remove unnecessary dev_info output (#1830) +Subject: [PATCH 127/207] gpio_mem: Remove unnecessary dev_info output (#1830) The open function was spamming syslog every time called, so have removed call completely. @@ -126803,10 +126803,10 @@ index 911f5b7393ed48ceed8751f06967ae6463453f9c..f5e7f1ba8fb6f18dee77fad06a17480c dev_err(inst->dev, "Unknown minor device: %d", dev); ret = -ENXIO; -From b1b62c87da8a1c63ac438628c7045ceb65c5ded6 Mon Sep 17 00:00:00 2001 +From df374aeb7ad7acda1cd7513829fa8f963631878f Mon Sep 17 00:00:00 2001 From: Claggy3 Date: Sat, 11 Feb 2017 14:00:30 +0000 -Subject: [PATCH 128/205] Update vfpmodule.c +Subject: [PATCH 128/207] Update vfpmodule.c Christopher Alexander Tobias Schulze - May 2, 2015, 11:57 a.m. This patch fixes a problem with VFP state save and restore related @@ -126943,10 +126943,10 @@ index 569d5a650a4a2c6266ddf8fc6d38e0cd96b985f6..5822a3f60a96510201a6d88828ac5262 /* * Save the userland NEON/VFP state. Under UP, -From 804da841f3a609420fb083b4ed86ae5ffce4c278 Mon Sep 17 00:00:00 2001 +From 8c48304dcb78bfd96ca68fae21f1076d9dffd880 Mon Sep 17 00:00:00 2001 From: Michael Zoran Date: Sat, 11 Feb 2017 01:18:31 -0800 -Subject: [PATCH 129/205] ARM64: Force hardware emulation of deprecated +Subject: [PATCH 129/207] ARM64: Force hardware emulation of deprecated instructions. --- @@ -126974,10 +126974,10 @@ index ecf9298a12d48f11d5833dca0584d8ab028cf422..14e9146709857124891f8a3927efec87 case INSN_OBSOLETE: insn->current_mode = INSN_UNDEF; -From 47ba747eac45931aeeec011a676679b5beff5cff Mon Sep 17 00:00:00 2001 +From 81cd41ed62dbc799e1b991e8360bff950e471f42 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 13 Feb 2017 15:33:47 +0000 -Subject: [PATCH 130/205] squash: fix order of sound/soc/bcm makefile +Subject: [PATCH 130/207] squash: fix order of sound/soc/bcm makefile --- sound/soc/bcm/Makefile | 4 ++-- @@ -127016,10 +127016,10 @@ index 222a7583891f632cc2297f49aa1a58ee46507875..bb1df438540193652ec5464e8bc51f63 obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o -From b8f42d500be698354071fd7df6f7d5d025ec088e Mon Sep 17 00:00:00 2001 +From c6ab3ba3669e38e3c0fafb21a2e43b6b51caf454 Mon Sep 17 00:00:00 2001 From: Matthias Reichl Date: Sun, 22 Jan 2017 12:49:36 +0100 -Subject: [PATCH 131/205] config: Enable regulator support +Subject: [PATCH 131/207] config: Enable regulator support Signed-off-by: Matthias Reichl --- @@ -127054,10 +127054,10 @@ index 1927b1671b6eced73e4b4d76352bb4b1301d077c..5351a59b7f670985f47fdbafa2611734 CONFIG_MEDIA_CAMERA_SUPPORT=y CONFIG_MEDIA_ANALOG_TV_SUPPORT=y -From da4b9bd8d41de88049cf2df895ab5dddb2a0ea36 Mon Sep 17 00:00:00 2001 +From f5390ca93d425018d40b01b963a09547bbb0527d Mon Sep 17 00:00:00 2001 From: Matthias Reichl Date: Sun, 22 Jan 2017 12:49:36 +0100 -Subject: [PATCH 132/205] BCM270x DT: expose 3.3V and 5V system rails +Subject: [PATCH 132/207] BCM270x DT: expose 3.3V and 5V system rails Signed-off-by: Matthias Reichl --- @@ -127090,10 +127090,10 @@ index a46cb4a8b1419edd95e0e07c18b0f373222dc2bf..36d853715f2379e1952ce3d3be58dd67 + }; }; -From 199bc4807cdc54bc58a9a296bd782b004d243a3b Mon Sep 17 00:00:00 2001 +From 518964c678a1739dd7b13518d55f4607cb54a292 Mon Sep 17 00:00:00 2001 From: Matthias Reichl Date: Sun, 22 Jan 2017 12:49:36 +0100 -Subject: [PATCH 133/205] BCM270x DT: Consolidate audio card overlays +Subject: [PATCH 133/207] BCM270x DT: Consolidate audio card overlays Reference 3.3V / 5V system rails instead of instantiating local regulators. @@ -127388,10 +127388,10 @@ index 16b1247bfa618ff85936ddf78c3aea58075eaa67..f8d48233e28c7c18509b4a95692f6aff __overlay__ { compatible = "rra,digidac1-soundcard"; -From cbcf2f0c2e8e4929cba5304f1672dcc61327f9c8 Mon Sep 17 00:00:00 2001 +From 2a75c0777605da9f94d4d5578511767b4d41605f Mon Sep 17 00:00:00 2001 From: Matthias Reichl Date: Sun, 22 Jan 2017 12:49:37 +0100 -Subject: [PATCH 134/205] ASoC: Add driver for Cirrus Logic Audio Card +Subject: [PATCH 134/207] ASoC: Add driver for Cirrus Logic Audio Card Note: due to problems with deferred probing of regulators the following softdep should be added to a modprobe.d file @@ -128641,10 +128641,10 @@ index 0000000000000000000000000000000000000000..ac8651ddff7bd3701dffe22c7fb88352 +MODULE_DESCRIPTION("ASoC driver for Cirrus Logic Audio Card"); +MODULE_LICENSE("GPL"); -From ef840c3367c7fea8d1fb930969da7079d6536ff0 Mon Sep 17 00:00:00 2001 +From d2a557c6132c05e7e551bcf4d430f0d60293d454 Mon Sep 17 00:00:00 2001 From: Matthias Reichl Date: Sun, 22 Jan 2017 12:49:37 +0100 -Subject: [PATCH 135/205] config: enable Cirrus Logic Audio Card +Subject: [PATCH 135/207] config: enable Cirrus Logic Audio Card Signed-off-by: Matthias Reichl --- @@ -128693,10 +128693,10 @@ index 5351a59b7f670985f47fdbafa26117346cafe87d..062a89f0e5fc723559ddc5739e19eb20 CONFIG_SND_BCM2708_SOC_RPI_PROTO=m CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m -From 757055fad26c6a777ce221d407fb0c5241d227b8 Mon Sep 17 00:00:00 2001 +From 49703368126d094169a7eff851a9c477fd4c807e Mon Sep 17 00:00:00 2001 From: Martin Cerveny Date: Mon, 13 Feb 2017 17:23:47 +0100 -Subject: [PATCH 136/205] dwc_otg: fix summarize urb->actual_length for +Subject: [PATCH 136/207] dwc_otg: fix summarize urb->actual_length for isochronous transfers Kernel does not copy input data of ISO transfers to userspace @@ -128724,10 +128724,10 @@ index 162a656501988e56c9d780b7793d365fde09f801..992269d61ecf48126379a38e528f7190 dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_urb, i); } -From abd8c79c7ad6a4945cb08ae6c717c26b685e7660 Mon Sep 17 00:00:00 2001 +From 6ecb0a139b4597764c5653c31590940c3ff65e1a Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 13 Feb 2017 17:20:08 +0000 -Subject: [PATCH 137/205] clk-bcm2835: Mark used PLLs and dividers CRITICAL +Subject: [PATCH 137/207] clk-bcm2835: Mark used PLLs and dividers CRITICAL The VPU configures and relies on several PLLs and dividers. Mark all enabled dividers and their PLLs as CRITICAL to prevent the kernel from @@ -128755,10 +128755,10 @@ index 093694e00caec6e133eb26712f890691cad999aa..33bfa2008479153402d188d71d382f02 divider->data = data; -From f4329c4672193149bb33a774e5ad3fdaf58839db Mon Sep 17 00:00:00 2001 +From 02dbc844e23875bbf0dc41af2bc66066468fc14f Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 9 Feb 2017 14:33:30 +0000 -Subject: [PATCH 138/205] irq-bcm2836: Avoid "Invalid trigger warning" +Subject: [PATCH 138/207] irq-bcm2836: Avoid "Invalid trigger warning" Initialise the level for each IRQ to avoid a warning from the arm arch timer code. @@ -128782,10 +128782,10 @@ index 67dcac46cca72db4ebe2300eab04f0a867e8e14b..9a7ee04ee0d9b7aa734cf3159ed59c19 static void -From 39e05a38ed72307573d431b136c33c8fdcf5414a Mon Sep 17 00:00:00 2001 +From 0081bdaff2669ac8bf15888d42330d3681eab6cf Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 9 Feb 2017 14:36:44 +0000 -Subject: [PATCH 139/205] sound: Demote deferral errors to INFO level +Subject: [PATCH 139/207] sound: Demote deferral errors to INFO level At present there is no mechanism to specify driver load order, which can lead to deferrals and repeated retries until successful. @@ -128820,10 +128820,10 @@ index baa1afa41e3dd57fdc36655b7d3bbd147ade820f..0ddeffcc48d6c14f275ea6409d1a7de8 goto _err_defer; } -From 5dc3302c4af9bf5db340f72f3ae412de3d985f23 Mon Sep 17 00:00:00 2001 +From 83e36717ba0d6fa85215fcff4a0f0d5a7cf789b3 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 9 Feb 2017 14:40:33 +0000 -Subject: [PATCH 140/205] sound: Suppress error message about deferrals +Subject: [PATCH 140/207] sound: Suppress error message about deferrals Since driver load deferrals are expected and will already have resulted in a kernel message, suppress an essentially @@ -129070,10 +129070,10 @@ index 9db678e885efd63d84d60a098a84ed6772b19a2d..fadbfade100228aaafabb0d3bdf35c01 return ret; } -From ef17af903c96643c9ca25690f0551e8e3d2c9162 Mon Sep 17 00:00:00 2001 +From fcf96be7c69184c92ac07e6c509ef2ee34d7d6f1 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 17 Feb 2017 09:47:11 +0000 -Subject: [PATCH 141/205] BCM270X_DT: Add SMSC ethernet controller to DT +Subject: [PATCH 141/207] BCM270X_DT: Add SMSC ethernet controller to DT With an ethernet node in the DT, a suitable firmware can populate the local-mac-address property, removing the need for a downstream patch @@ -129136,10 +129136,10 @@ index 12764a3495b2372ffaf47e32ea0d21326ca83686..2a5b512d3e1acb17c6a40bf9d370f222 / { model = "Raspberry Pi 3 Model B"; -From 3318bc0830570e6913aff04ebaf543f7cc3eaade Mon Sep 17 00:00:00 2001 +From bc3f78482a388d33bd3291c81708c2da8f89faf1 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 17 Feb 2017 15:26:13 +0000 -Subject: [PATCH 142/205] brcmfmac: Mute expected startup 'errors' +Subject: [PATCH 142/207] brcmfmac: Mute expected startup 'errors' The brcmfmac WiFi driver always complains about the '00' country code and the firmware version is reported as an error. Modify the driver to @@ -129178,10 +129178,10 @@ index 4051780f64f44a5ce522babe6c371a1beb79a824..b081673abcb4aa72d70d8e0834b608f6 /* locate firmware version number for ethtool */ ptr = strrchr(buf, ' ') + 1; -From 6cdf7ca77467b26d5f80bc3b94e46b197f65c9c4 Mon Sep 17 00:00:00 2001 +From 042141f1266a63d6c7f92bdf9f19a1a7d5543342 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 13 Feb 2017 17:20:08 +0000 -Subject: [PATCH 143/205] clk-bcm2835: Add claim-clocks property +Subject: [PATCH 143/207] clk-bcm2835: Add claim-clocks property The claim-clocks property can be used to prevent PLLs and dividers from being marked as critical. It contains a vector of clock IDs, @@ -129317,10 +129317,10 @@ index 33bfa2008479153402d188d71d382f0274c104ea..0b62d20f8b718cfd03c0346af784688e if (!cprman->osc_name) return -ENODEV; -From 37081d10d9efc9a65081979419a3fa5518069872 Mon Sep 17 00:00:00 2001 +From d684cb6db6f70cd7784b6a68ebe8a38c5acc844c Mon Sep 17 00:00:00 2001 From: Matthias Reichl Date: Mon, 20 Feb 2017 20:01:16 +0100 -Subject: [PATCH 144/205] dmaengine: bcm2835: Fix cyclic DMA period splitting +Subject: [PATCH 144/207] dmaengine: bcm2835: Fix cyclic DMA period splitting The code responsible for splitting periods into chunks that can be handled by the DMA controller missed to update total_len, @@ -129359,10 +129359,10 @@ index 80d35f760b4a4a51e60c355a84d538bac3892a4d..599c218dc8a73172dd4bd4a058fc8f95 /* calculate the length that remains to reach period_length */ control_block->length = period_len - *total_len; -From 7d1ca67d29af5f81e531881e50a45a81002cfa2c Mon Sep 17 00:00:00 2001 +From 5f095ee8608e56d7af66ac0d788c6d3d754a5dcc Mon Sep 17 00:00:00 2001 From: Scott Ellis Date: Thu, 23 Feb 2017 11:56:20 -0500 -Subject: [PATCH 145/205] config: Add ads1015 driver to config +Subject: [PATCH 145/207] config: Add ads1015 driver to config --- arch/arm/configs/bcm2709_defconfig | 1 + @@ -129394,10 +129394,10 @@ index 062a89f0e5fc723559ddc5739e19eb20c030f0f1..97b88dcbc1e6c5b16540622222715777 CONFIG_THERMAL=y CONFIG_THERMAL_BCM2835=y -From f3806a3df4befc70394a17040ac9daf1170f798f Mon Sep 17 00:00:00 2001 +From 693c781670bd5e5c23565318e949bb0ac474d442 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 27 Jan 2017 18:49:30 +0000 -Subject: [PATCH 146/205] config: add slcan kernel module +Subject: [PATCH 146/207] config: add slcan kernel module See: https://github.com/raspberrypi/linux/issues/1819 --- @@ -129430,10 +129430,10 @@ index 97b88dcbc1e6c5b165406222227157776b162801..2cfa65bc83fd4b7e802f56965543a217 CONFIG_IRDA=m CONFIG_IRLAN=m -From 542d055d729d7a61aea12d8c0c0dd6ae2b2d779a Mon Sep 17 00:00:00 2001 +From 3914dc99e10eee67b08c38b1bca2027cfd50d940 Mon Sep 17 00:00:00 2001 From: Miquel Date: Fri, 24 Feb 2017 20:51:06 +0100 -Subject: [PATCH 147/205] sound: Support for Dion Audio LOCO-V2 DAC-AMP HAT +Subject: [PATCH 147/207] sound: Support for Dion Audio LOCO-V2 DAC-AMP HAT Signed-off-by: Miquel Blauw --- @@ -129754,10 +129754,10 @@ index 0000000000000000000000000000000000000000..a009c49477972a9832175d86f201b035 +MODULE_DESCRIPTION("ASoC Driver for DionAudio LOCO-V2"); +MODULE_LICENSE("GPL v2"); -From 35fd1d089c90cdcb13c8b813e1ca913fff911fb4 Mon Sep 17 00:00:00 2001 +From 3a6fe281672bffd19347d18fd98c883612fff47e Mon Sep 17 00:00:00 2001 From: Fe-Pi Date: Wed, 1 Mar 2017 04:42:43 -0700 -Subject: [PATCH 148/205] Add support for Fe-Pi audio sound card. (#1867) +Subject: [PATCH 148/207] Add support for Fe-Pi audio sound card. (#1867) Fe-Pi Audio Sound Card is based on NXP SGTL5000 codec. Mechanical specification of the board is the same the Raspberry Pi Zero. @@ -130106,10 +130106,10 @@ index 0000000000000000000000000000000000000000..015b56fd73cc36be5b5eecd17548fd03 +MODULE_DESCRIPTION("ASoC Driver for Fe-Pi Audio"); +MODULE_LICENSE("GPL v2"); -From adf9206b5b10b7166b5e135d7d77c250eebd62cf Mon Sep 17 00:00:00 2001 +From 18f2c9474e7f297b4b3a82e5e3e6a2cded033666 Mon Sep 17 00:00:00 2001 From: Scott Ellis Date: Wed, 1 Mar 2017 07:22:24 -0500 -Subject: [PATCH 149/205] Add overlay for ads1115 ADCs (#1864) +Subject: [PATCH 149/207] Add overlay for ads1115 ADCs (#1864) --- arch/arm/boot/dts/overlays/Makefile | 1 + @@ -130273,10 +130273,10 @@ index 0000000000000000000000000000000000000000..7c16a1af3172d14e1a976b1776b9f167 + }; +}; -From 3d3c58bb2c93082bd66fc2f63cbfdcc6d29289ba Mon Sep 17 00:00:00 2001 +From 9db96c5402d36038bf9dc15182c0d7d833c4fbfd Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 1 Mar 2017 16:06:53 +0000 -Subject: [PATCH 150/205] clk-bcm2835: Correct the prediv logic +Subject: [PATCH 150/207] clk-bcm2835: Correct the prediv logic If a clock has the prediv flag set, both the integer and fractional parts must be scaled when calculating the resulting frequency. @@ -130303,10 +130303,10 @@ index 0b62d20f8b718cfd03c0346af784688e26e9dcb6..ef0d05c58573f62de3632a920dfc1988 return bcm2835_pll_rate_from_divisors(parent_rate, ndiv, fdiv, pdiv); } -From 43eae625eeca47fa356a0ea47ce3a99da67054b2 Mon Sep 17 00:00:00 2001 +From 5cc03cc1e4aa62ff6c926be5e7e4fbf54492bb01 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 1 Mar 2017 16:07:39 +0000 -Subject: [PATCH 151/205] amba_pl011: Round input clock up +Subject: [PATCH 151/207] amba_pl011: Round input clock up The UART clock is initialised to be as close to the requested frequency as possible without exceeding it. Now that there is a @@ -130392,10 +130392,10 @@ index 6beb6233a0b6132b933cf8d85d8501dc1ce2fe4c..50792f9fa8fc530e2ecbc90f92adb11b /* unregisters the driver also if no more ports are left */ static void pl011_unregister_port(struct uart_amba_port *uap) -From c93cc959a79f234cd616079e0c92b6c7614c87b9 Mon Sep 17 00:00:00 2001 +From fe38d14706f1f505f452f498b80aea3504ee682e Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 13 Feb 2017 11:10:50 +0000 -Subject: [PATCH 152/205] BCM2835-V4L2: Ensure H264 header bytes get a sensible +Subject: [PATCH 152/207] BCM2835-V4L2: Ensure H264 header bytes get a sensible timestamp H264 header come off VC with 0 timestamps, which means they get a @@ -130484,10 +130484,10 @@ index e6aeb7e7e381de65d6c6586205069a4c5cd33274..7f8a68916a67001bc9241bce2928519a struct vchiq_mmal_port *port; /* port being used for capture */ /* camera port being used for capture */ -From b8dcca2e5f532286c765b078fba537bb0bb2f51a Mon Sep 17 00:00:00 2001 +From 62567be1a6cbdc27a935e45ef4130fc310c82aab Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 13 Feb 2017 13:11:41 +0000 -Subject: [PATCH 153/205] BCM2835-V4L2: Correctly denote key frames in encoded +Subject: [PATCH 153/207] BCM2835-V4L2: Correctly denote key frames in encoded data Forward MMAL key frame flags to the V4L2 buffers. @@ -130512,10 +130512,10 @@ index e69731320f4e59249933bc21843913deab4a1209..6bdec0806126044cf7146d53326e4da5 "Buffer has ts %llu", dev->capture.last_timestamp); -From 050edc69c5ae652f09a19e717bdc6e3e8a5d7db7 Mon Sep 17 00:00:00 2001 +From 4e456d9a69677612591a933606e67694789ec3ad Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 20 Feb 2017 17:01:21 +0000 -Subject: [PATCH 154/205] bcm2835-gpio-exp: Driver for GPIO expander via +Subject: [PATCH 154/207] bcm2835-gpio-exp: Driver for GPIO expander via mailbox service Pi3 and Compute Module 3 have a GPIO expander that the @@ -130933,10 +130933,10 @@ index 280791fb9656901392ce67e44cb742c96f090ed4..dc7fd58afd5dddebf9b17065bb069a1d /* Dispmanx TAGS */ RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE = 0x00040001, -From 4f512a78f2268d56ac83d4fd231d4e496295db50 Mon Sep 17 00:00:00 2001 +From 07ae16568897b3b22613e2bb3e4942d4a0a2521f Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 24 May 2016 16:30:05 +0100 -Subject: [PATCH 155/205] BCM270X_DT: Add bcm2708-rpi-0-w.dts +Subject: [PATCH 155/207] BCM270X_DT: Add bcm2708-rpi-0-w.dts Add DT support for the Pi Zero W. N.B. It will not be loaded automatically without a corresponding change to the firmware. @@ -131164,10 +131164,10 @@ index 0000000000000000000000000000000000000000..db0f99ddf2f46e83827d56e21c4846dd + }; +}; -From a2b0bace6b21a4bc0ad502b6462192c80e7e72a0 Mon Sep 17 00:00:00 2001 +From 94f74f7bcedbd08e23cbf603d2f816388617fde1 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 6 Mar 2017 09:06:18 +0000 -Subject: [PATCH 156/205] clk-bcm2835: Read max core clock from firmware +Subject: [PATCH 156/207] clk-bcm2835: Read max core clock from firmware The VPU is responsible for managing the core clock, usually under direction from the bcm2835-cpufreq driver but not via the clk-bcm2835 @@ -131291,10 +131291,10 @@ index ef0d05c58573f62de3632a920dfc19888c019d18..41dccc4ebe6f367054822aed11cb0cd4 for (i = 0; !of_property_read_u32_index(pdev->dev.of_node, "claim-clocks", -From 70b2f53432c77438fabf2ba6ec9d050ef689b61d Mon Sep 17 00:00:00 2001 +From 716434121d8e5d927bf21434f96ee49c115d41ce Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 7 Mar 2017 19:48:23 +0000 -Subject: [PATCH 157/205] config: Add CONFIG_CRYPTO_LZ4 +Subject: [PATCH 157/207] config: Add CONFIG_CRYPTO_LZ4 Enabling this options allows LZ4 memory compression. @@ -131331,10 +131331,10 @@ index a9c46f902eb32b364423d8bef07b6b37f798c617..e5996d77b02303c4b43e62a810e0e3e6 # CONFIG_CRYPTO_HW is not set CONFIG_ARM_CRYPTO=y -From c07a03823b0e3f3c32983e7dfe27756a1f43a40b Mon Sep 17 00:00:00 2001 +From 7218b6ac1104e494254ad49eba0ab2f594c6c007 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 5 Mar 2017 11:46:41 +0000 -Subject: [PATCH 158/205] config: Add RTL8XXXU wifi module +Subject: [PATCH 158/207] config: Add RTL8XXXU wifi module --- arch/arm/configs/bcm2709_defconfig | 1 + @@ -131366,10 +131366,10 @@ index e5996d77b02303c4b43e62a810e0e3e660c1e99e..a691ce8b7fb6017fcc7990cf08e8ff4a CONFIG_ZD1211RW=m CONFIG_MAC80211_HWSIM=m -From da801d0435c282b9c30f48c44c17690ce5226a5b Mon Sep 17 00:00:00 2001 +From e15e00021c1e366c5c48beb520e0a9b3ee4987f7 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Fri, 10 Mar 2017 14:43:15 +0000 -Subject: [PATCH 159/205] bcm2835-v4l2: Fix buffer overflow problem +Subject: [PATCH 159/207] bcm2835-v4l2: Fix buffer overflow problem https://github.com/raspberrypi/linux/issues/1447 port_parameter_get() failed to account for the header @@ -131405,10 +131405,10 @@ index 781322542d5a8295f3d7d5a3eaaf0cac29930c30..e4b243b33f58913f3d2952c97d2a2e3f * but report true size of parameter */ -From 30696eebe3d3cd688bac2080d822b9147c1d30b6 Mon Sep 17 00:00:00 2001 +From 317616bd35c7c822863123f19ecd66ed17ad12a1 Mon Sep 17 00:00:00 2001 From: Matt Flax Date: Wed, 8 Mar 2017 20:04:13 +1100 -Subject: [PATCH 160/205] Add support for the AudioInjector.net Octo sound card +Subject: [PATCH 160/207] Add support for the AudioInjector.net Octo sound card --- arch/arm/boot/dts/overlays/Makefile | 1 + @@ -131879,10 +131879,10 @@ index 0000000000000000000000000000000000000000..9effea725798640887755dfa688da453 +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:audioinjector-octo-soundcard"); -From d4396f35aba993cb4b83698c44b1c1d6c1c661c1 Mon Sep 17 00:00:00 2001 +From 9eee684c088a08e0887c653e768bc31189430155 Mon Sep 17 00:00:00 2001 From: Matt Flax Date: Wed, 8 Mar 2017 21:13:24 +1100 -Subject: [PATCH 161/205] ASoC: bcm2835_i2s.c: relax the ch2 register setting +Subject: [PATCH 161/207] ASoC: bcm2835_i2s.c: relax the ch2 register setting for 8 channels This patch allows ch2 registers to be set for 8 channels of audio. @@ -131911,10 +131911,10 @@ index 6ba20498202ed36906b52096893a88867a79269f..c8dd065aea8414b47aa2ea4fc04168b5 format |= BCM2835_I2S_CH1(BCM2835_I2S_CHPOS(ch1pos)); format |= BCM2835_I2S_CH2(BCM2835_I2S_CHPOS(ch2pos)); -From da15c69893e44bafda6f581df5841347f2a3a29d Mon Sep 17 00:00:00 2001 +From ca0a0a0404a18577d24bfa18c3e134c22e38482a Mon Sep 17 00:00:00 2001 From: Khem Raj Date: Fri, 10 Feb 2017 17:57:08 -0800 -Subject: [PATCH 162/205] build/arm64: Add rules for .dtbo files for dts +Subject: [PATCH 162/207] build/arm64: Add rules for .dtbo files for dts overlays We now create overlays as .dtbo files. @@ -131939,10 +131939,10 @@ index b9a4a934ca057623e0ea436fd9b2c7c0f675fced..54e3c38d6fd877827541cdc798de035c dtbs: prepare scripts -From 6006b9d774319d07169f5371535d36a37dd4d165 Mon Sep 17 00:00:00 2001 +From 1b1e44fe1b30e2d0a506ec563e068003f08ec785 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 24 Feb 2015 13:40:50 +0000 -Subject: [PATCH 163/205] pinctrl-bcm2835: Fix interrupt handling for GPIOs +Subject: [PATCH 163/207] pinctrl-bcm2835: Fix interrupt handling for GPIOs 28-31 and 46-53 Contrary to the documentation, the BCM2835 GPIO controller actually has @@ -131975,10 +131975,10 @@ index 6351fe7f8e314ac5ebb102dd20847b383fd5b857..28745af5aadf3cb91fa7ff39118385c3 }, }; -From 241087fd2e533f54f335d30412663fa5f5cc1b3a Mon Sep 17 00:00:00 2001 +From ad97ba4e4b11f54e632eef44799debcc1da9a679 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 9 May 2016 17:28:18 -0700 -Subject: [PATCH 164/205] clk: bcm2835: Mark GPIO clocks enabled at boot as +Subject: [PATCH 164/207] clk: bcm2835: Mark GPIO clocks enabled at boot as critical. These divide off of PLLD_PER and are used for the ethernet and wifi @@ -132016,10 +132016,10 @@ index 41dccc4ebe6f367054822aed11cb0cd4d985c21a..7ec0e71cbcfbcd6c86e2f6c8080e1d62 * rate changes on at least of the parents. */ -From 843f389a764aca2a65cf11e9a97a1a9a0b825804 Mon Sep 17 00:00:00 2001 +From 517805f8a01305aefecb69dce839e9a1071ce3b2 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 7 Mar 2016 15:05:11 +0000 -Subject: [PATCH 165/205] vchiq_arm: Tweak the logging output +Subject: [PATCH 165/207] vchiq_arm: Tweak the logging output Signed-off-by: Phil Elwell --- @@ -132094,10 +132094,10 @@ index d6757ee263fb61a689c0d38c0dbb65c57a8e39bb..7fd63cf6800d7ec35fbcb215a283630c switch (type) { -From 5d8d385e94e0ed70b78deb80b4d76e917a87740d Mon Sep 17 00:00:00 2001 +From bb8fda2820495e0b2177304be1a31fc5d949e1da Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 18 Jan 2017 07:31:55 +1100 -Subject: [PATCH 166/205] clk: bcm2835: Don't rate change PLLs on behalf of DSI +Subject: [PATCH 166/207] clk: bcm2835: Don't rate change PLLs on behalf of DSI PLL dividers. Our core PLLs are intended to be configured once and left alone. With @@ -132269,10 +132269,10 @@ index 7ec0e71cbcfbcd6c86e2f6c8080e1d622ca5540a..3acf61ddeda8c27e6da0fd7e2beb4634 /* the clocks */ -From 9f9e42cd33e80d28d66ab491e7f64bf45827cbef Mon Sep 17 00:00:00 2001 +From 0f7d4e9404dca7f9c399e57038397bc10dd62616 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 18 Jan 2017 07:31:56 +1100 -Subject: [PATCH 167/205] clk: bcm2835: Register the DSI0/DSI1 pixel clocks. +Subject: [PATCH 167/207] clk: bcm2835: Register the DSI0/DSI1 pixel clocks. The DSI pixel clocks are muxed from clocks generated in the analog phy by the DSI driver. In order to set them as parents, we need to do the @@ -132515,10 +132515,10 @@ index 360e00cefd35679b49890234b5c369fb52b89e20..a0c812b0fa391d149b4f546db39bdc4b +#define BCM2835_CLOCK_DSI0P 49 +#define BCM2835_CLOCK_DSI1P 50 -From 88280e5253dc5208761c6deb8177177c8e2f8aad Mon Sep 17 00:00:00 2001 +From 47f1767c3185e5c7aed5cf167c8ef5d20e452a2e Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 18 Jan 2017 07:31:57 +1100 -Subject: [PATCH 168/205] clk: bcm2835: Add leaf clock measurement support, +Subject: [PATCH 168/207] clk: bcm2835: Add leaf clock measurement support, disabled by default This proved incredibly useful during debugging of the DSI driver, to @@ -132864,10 +132864,10 @@ index 428e75c8b970897d881b570228eb85e8aef28999..fe3298b54cdfb96bd90fb4f39e13921d /* the gates */ -From d360cbaa24f90de7d42760f8f7de74e4cbfedad7 Mon Sep 17 00:00:00 2001 +From 238c3066704b1c90252182cc4f641a6c9fb847df Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 26 Apr 2016 13:46:13 -0700 -Subject: [PATCH 169/205] drm/panel: Add support for the Raspberry Pi 7" +Subject: [PATCH 169/207] drm/panel: Add support for the Raspberry Pi 7" Touchscreen. This driver communicates with the Atmel microcontroller for sequencing @@ -133448,10 +133448,10 @@ index 0000000000000000000000000000000000000000..1a536fe4d040f5fafe324baee110a622 +MODULE_DESCRIPTION("Raspberry Pi 7-inch touchscreen driver"); +MODULE_LICENSE("GPL v2"); -From c5101c0993c27727c53ba280c1f5cb06a95fb9b8 Mon Sep 17 00:00:00 2001 +From ab69153689e1d39c1f19db1db844276a0da6d304 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 2 Jun 2016 12:29:45 -0700 -Subject: [PATCH 170/205] BCM270X: Add the DSI panel to the defconfig. +Subject: [PATCH 170/207] BCM270X: Add the DSI panel to the defconfig. Signed-off-by: Eric Anholt --- @@ -133500,10 +133500,10 @@ index 4d85c231c5ea0244e1b05fb4a5e3c8fd3e651ddf..baf316e3a69d421d79ec098c7ad2603c CONFIG_DRM_VC4=m CONFIG_FB=y -From d6049f3593bfd89125a0fb61a3c1e5873fa65308 Mon Sep 17 00:00:00 2001 +From 1ced6f0aef205e162bc9696c96d602b7cdc1db91 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 13 Dec 2016 15:15:10 -0800 -Subject: [PATCH 171/205] ARM: bcm2835: dt: Add the DSI module nodes and +Subject: [PATCH 171/207] ARM: bcm2835: dt: Add the DSI module nodes and clocks. The modules stay disabled by default, and if you want to enable DSI @@ -133607,10 +133607,10 @@ index b710a4d67b8ec8c8c18ce8efb6f270e7cfb68e52..304dd291a9ae94700e8e628c0c9ebd3f compatible = "brcm,bcm2835-i2c"; reg = <0x7e804000 0x1000>; -From 8e0d7ffe0ef3d438eb3e0a5ef1867cc6c88a0bc0 Mon Sep 17 00:00:00 2001 +From f782a664bf178f59448b876c6d26f66f1100fd3a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 2 Jun 2016 15:09:35 -0700 -Subject: [PATCH 172/205] BCM270X: Enable the DSI panel node in the VC4 +Subject: [PATCH 172/207] BCM270X: Enable the DSI panel node in the VC4 overlay. Signed-off-by: Eric Anholt @@ -133763,10 +133763,10 @@ index fb45c6456b181b047d6cff8784f7696eb75da3c7..05faf1bfa1b7c73fd60b1efb813b969e __overlay__ { claim-clocks = < -From e0ad51b3f5630c4a2b2891d72c61d38a04aa37c3 Mon Sep 17 00:00:00 2001 +From e1c1dca8df5d830a238e068470b92b5c69364b49 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 15 Sep 2016 15:25:23 +0100 -Subject: [PATCH 173/205] drm/vc4: Set up SCALER_DISPCTRL at boot. +Subject: [PATCH 173/207] drm/vc4: Set up SCALER_DISPCTRL at boot. We want the HVS on, obviously, and we also want DSP3 (PV1's source) to be muxed from HVS channel 2 like we expect in vc4_crtc.c. The @@ -133826,10 +133826,10 @@ index 39f6886b24100c43b590e47e0c7bc44846721d65..b3b297fba7097bc495fa8916292c5479 * SCALER_DISPSTAT_IRQDISP0. Note that short frame contributions are * always enabled. -From 93a7172e9edfe359fa4b4b9c002c0a2324347235 Mon Sep 17 00:00:00 2001 +From e771f742e59b6c20aec848d81056dee34b504efa Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 10 Feb 2016 16:17:29 -0800 -Subject: [PATCH 174/205] drm/vc4: Add support for feeding DSI encoders from +Subject: [PATCH 174/207] drm/vc4: Add support for feeding DSI encoders from the pixel valve. We have to set a different pixel format, which tells the hardware to @@ -133944,10 +133944,10 @@ index b3b297fba7097bc495fa8916292c547925720199..385405a2df05eb3dd86d4f687aa82053 # define PV_VCONTROL_VIDEN BIT(0) -From 5cc0c887f8f855807eb0ed4788a287b17c3023b9 Mon Sep 17 00:00:00 2001 +From 78b9942bfad405b0c93edf523ac144655f7d5106 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 10 Feb 2016 11:42:32 -0800 -Subject: [PATCH 175/205] drm/vc4: Add DSI driver +Subject: [PATCH 175/207] drm/vc4: Add DSI driver The DSI0 and DSI1 blocks on the 2835 are related hardware blocks. Some registers move around, and the featureset is slightly different, @@ -135775,10 +135775,10 @@ index 0000000000000000000000000000000000000000..17fcac381dbb37cd9a5ff210ad8578f4 + }, +}; -From 95dd80652c49816379b9022b3a712f2ebef958c1 Mon Sep 17 00:00:00 2001 +From 44e48aaa5b21f92d8e1e93b2d3e852ab0dbb83b6 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 2 Dec 2016 14:48:12 +0100 -Subject: [PATCH 176/205] ARM: dts: bcm283x: Add VEC node in bcm283x.dtsi +Subject: [PATCH 176/207] ARM: dts: bcm283x: Add VEC node in bcm283x.dtsi Add the VEC (Video EnCoder) node definition in bcm283x.dtsi. @@ -135809,10 +135809,10 @@ index 304dd291a9ae94700e8e628c0c9ebd3fb98abb19..ee69fd481fabd22d8f45ecdcffacdbb1 compatible = "brcm,bcm2835-pixelvalve2"; reg = <0x7e807000 0x100>; -From 8b3c5ccc22f7a4ae27dc91bb481c3bdfa1d0ae51 Mon Sep 17 00:00:00 2001 +From 051dca643787b83494b3354660b9f041727543d9 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 2 Dec 2016 14:48:13 +0100 -Subject: [PATCH 177/205] ARM: dts: bcm283x: Enable the VEC IP on all +Subject: [PATCH 177/207] ARM: dts: bcm283x: Enable the VEC IP on all RaspberryPi boards Enable the VEC IP on all RaspberryPi boards. @@ -135838,10 +135838,10 @@ index 58f7d874c70a9cf965e10ae3f14fe3bb00846b71..023630efa7c1d8601ba5e83d2fdb38a7 + status = "okay"; +}; -From 16989487bc5e3c46301c9011df30234745f7f832 Mon Sep 17 00:00:00 2001 +From bc0d23048b0f2560e6508fe11c5352bf42e8aa4f Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 23 Jan 2017 11:41:54 -0800 -Subject: [PATCH 178/205] BCM270X: Disable VEC unless vc4-kms-v3d is present. +Subject: [PATCH 178/207] BCM270X: Disable VEC unless vc4-kms-v3d is present. Signed-off-by: Eric Anholt --- @@ -135880,10 +135880,10 @@ index 05faf1bfa1b7c73fd60b1efb813b969e10bbfefa..c57e795824e9261e0f60bcb40d6a5724 __overlay__ { claim-clocks = < -From 2e9eca32000d2f285410684372be193dad6a3243 Mon Sep 17 00:00:00 2001 +From 2c704ce1abf3907ab482e4cfdb8e5874ffbdc8e4 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 1 Feb 2017 17:09:18 -0800 -Subject: [PATCH 179/205] drm/vc4: Name the primary and cursor planes in fkms. +Subject: [PATCH 179/207] drm/vc4: Name the primary and cursor planes in fkms. This makes debugging nicer, compared to trying to remember what the IDs are. @@ -135907,10 +135907,10 @@ index d18a1dae51a2275846c9826b5bf1ba57ae97b55c..e49ce68b607a7ffc2329e3235362f3bc if (type == DRM_PLANE_TYPE_PRIMARY) { vc4_plane->fbinfo = -From 41e1bdd573c73ae7e92816aa3ead8e773fc43c74 Mon Sep 17 00:00:00 2001 +From 54aaa723397c81a4e2045ce6fa5b97637a935122 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 1 Feb 2017 17:10:09 -0800 -Subject: [PATCH 180/205] drm/vc4: Add DRM_DEBUG_ATOMIC for the insides of +Subject: [PATCH 180/207] drm/vc4: Add DRM_DEBUG_ATOMIC for the insides of fkms. Trying to debug weston on fkms involved figuring out what calls I was @@ -135980,10 +135980,10 @@ index e49ce68b607a7ffc2329e3235362f3bc21ed5cbb..dbf065677202fbebf8e3a0cffbe880aa RPI_FIRMWARE_SET_CURSOR_STATE, &packet_state, -From 97ea26709858bbfe01b27a15fc32b0a3676551d2 Mon Sep 17 00:00:00 2001 +From a59111e91442409d81057e1f59944d2c5d9d8977 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 2 Feb 2017 09:42:18 -0800 -Subject: [PATCH 181/205] drm/vc4: Fix sending of page flip completion events +Subject: [PATCH 181/207] drm/vc4: Fix sending of page flip completion events in FKMS mode. In the rewrite of vc4_crtc.c for fkms, I dropped the part of the @@ -136025,10 +136025,10 @@ index dbf065677202fbebf8e3a0cffbe880aa42daef3f..da818a207bfa639b8cea48d94bcf4566 static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc) -From d43138fbb9983b0c48a797e47c56031f0f896856 Mon Sep 17 00:00:00 2001 +From eae720bd63aa3991f260f0f2a73b3da5430de81e Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 8 Feb 2017 15:00:54 -0800 -Subject: [PATCH 182/205] drm/vc4: Fulfill user BO creation requests from the +Subject: [PATCH 182/207] drm/vc4: Fulfill user BO creation requests from the kernel BO cache. The from_cache flag was actually "the BO is invisible to userspace", @@ -136081,10 +136081,10 @@ index 3f6704cf6608d7be47637c6aa585de087b7f74ee..5ec14f25625dde6fd61e10415092fa25 cma_obj = drm_gem_cma_create(dev, size); -From 67acfa696e366610218724d8916c4d1de88da936 Mon Sep 17 00:00:00 2001 +From 19579bbd9cae7a6227f86559b5df2ba83161dc0a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 9 Feb 2017 09:23:34 -0800 -Subject: [PATCH 183/205] drm/vc4: Fix OOPSes from trying to cache a partially +Subject: [PATCH 183/207] drm/vc4: Fix OOPSes from trying to cache a partially constructed BO. If a CMA allocation failed, the partially constructed BO would be @@ -136118,10 +136118,10 @@ index 5ec14f25625dde6fd61e10415092fa25527cc151..fd83a28076564b9ea5cf0f2ba29b884e if (!cache_list) { vc4_bo_destroy(bo); -From 4ee40c73bb65066ed4e12ae9b26955abc74935ff Mon Sep 17 00:00:00 2001 +From 6c3d0b01657f721ad44a841727f2f8b8e857f340 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 12 Oct 2015 08:58:08 -0700 -Subject: [PATCH 184/205] drm/vc4: Verify at boot that CMA doesn't cross a +Subject: [PATCH 184/207] drm/vc4: Verify at boot that CMA doesn't cross a 256MB boundary. I've seen lots of users cranking CMA up higher, so throw an error if @@ -136204,10 +136204,10 @@ index c960459eda7e640ea55be1d4ed80c6a9125a8877..b50245282a18bc790da0f901944c2e67 static unsigned long cma_bitmap_aligned_mask(const struct cma *cma, int align_order) -From 5dc532d4756ce409c6e1f9673c6f8e4787e8444a Mon Sep 17 00:00:00 2001 +From 5ffa6fec5e28088dda49238bf58ec40cc4084eb7 Mon Sep 17 00:00:00 2001 From: Scott Ellis Date: Thu, 23 Feb 2017 11:56:20 -0500 -Subject: [PATCH 185/205] Add ads1015 driver to config +Subject: [PATCH 185/207] Add ads1015 driver to config --- arch/arm/configs/bcm2709_defconfig | 2 +- @@ -136245,10 +136245,10 @@ index 0768998e5cbcc96714d546f656ff59eafe2dc754..efc4898aca911d5c97426a38b0f1808b CONFIG_FB=y CONFIG_FB_BCM2708=y -From 9e458e70eeb9ecae5c0f0ec7ddcbe8fe87c32d0a Mon Sep 17 00:00:00 2001 +From 7069e623c20b4c59e2ce0b0c273119f511c930e1 Mon Sep 17 00:00:00 2001 From: Michael Zoran Date: Thu, 23 Feb 2017 17:54:31 -0800 -Subject: [PATCH 186/205] drm/vc4: Don't wait for vblank when updating the +Subject: [PATCH 186/207] drm/vc4: Don't wait for vblank when updating the cursor Commonly used desktop environments such as xfce4 and gnome @@ -136305,10 +136305,10 @@ index 686cdd3c86f2e9178768282a0dd173850e0bf063..7bdbb0e2b50f9202efe1177df761b379 * expected change from the drm_mode_cursor_universal() * helper. -From e0f85d10d7ed31141d7e7be16a32f49126ea4a1c Mon Sep 17 00:00:00 2001 +From 6e5b90f247a35d8724469c2344b330de9826615d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 6 Mar 2017 12:17:16 -0800 -Subject: [PATCH 187/205] panel-raspberrypi-touchscreen: Round up clk rate to +Subject: [PATCH 187/207] panel-raspberrypi-touchscreen: Round up clk rate to fix DSI panel. Commit 488f9bc8e3def93e0baef53cee2026c2cb0d8956 slightly increased the @@ -136343,10 +136343,10 @@ index 1a536fe4d040f5fafe324baee110a6225dd0be08..7f315f04b109621ca7f3861fdd8acf95 .hsync_start = HACT + HFP, .hsync_end = HACT + HFP + HSW, -From 1659209e09cb980be0ce9355594cb82708b12d44 Mon Sep 17 00:00:00 2001 +From 10bd8c8d097ef157a85f9939055620cbc41f6463 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 13 Mar 2017 12:30:37 +0000 -Subject: [PATCH 188/205] thermal: Compatible strings for bcm2836, bcm2837 +Subject: [PATCH 188/207] thermal: Compatible strings for bcm2836, bcm2837 The upstream dt-bindings documentation for bcm2835-thermal (which exists even though the driver isn't upstreamed) says to use @@ -136378,10 +136378,10 @@ index c63fb9f9d143e19612a18fe530c7b2b3518a22a4..25b78c3eac1503fbc9e679b963a6284b }; MODULE_DEVICE_TABLE(of, bcm2835_thermal_of_match_table); -From 6d74a91a6cf9071b6b85768dd248c08ececef46e Mon Sep 17 00:00:00 2001 +From d1e71ad4f7500f0656c2ee2a081d2dd85485311c Mon Sep 17 00:00:00 2001 From: John Greb Date: Wed, 8 Mar 2017 15:12:29 +0000 -Subject: [PATCH 189/205] Match dwc2 device-tree fifo sizes to the hardware +Subject: [PATCH 189/207] Match dwc2 device-tree fifo sizes to the hardware values. Since commit aa381a7259c3f53727bcaa8c5f9359e940a0e3fd was reverted with 3fa9538539ac737096c81f3315a14670b1609092 the g-tx-fifo-size array in the device-tree needs to match the preset values in the bcm2835. @@ -136412,10 +136412,10 @@ index 527abc9f0ddf71f4dc7d58336d87684c931cc2f3..265a16bab008453edba198cf2366c423 }; }; -From a5ee8a6256c58fadd572d12b509d01dcc6b8f25b Mon Sep 17 00:00:00 2001 +From 2e2bac7f1ac1c5fee5566dd59436ece713d44d25 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Tue, 7 Mar 2017 12:18:20 +0000 -Subject: [PATCH 190/205] BCM270X_DT: Invert Pi3 power LED to match fw change +Subject: [PATCH 190/207] BCM270X_DT: Invert Pi3 power LED to match fw change Firmware expgpio driver reworked due to complaint over hotplug detect. @@ -136441,10 +136441,10 @@ index 173103aaca503833b5e29530ed94e14c7cab0444..b21d2866d204adc533b46d581028f290 }; -From 4a722f8e4fb8a0eb65333a7e6e9534c56c193dc0 Mon Sep 17 00:00:00 2001 +From 6492ee82f575a250c26ce60896de3a0aa70c70eb Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 14 Mar 2017 09:10:05 +0000 -Subject: [PATCH 191/205] BCM270X_DT: Add lm75 to i2c-sensor overlay +Subject: [PATCH 191/207] BCM270X_DT: Add lm75 to i2c-sensor overlay See: https://www.raspberrypi.org/forums/viewtopic.php?f=107&t=177236 @@ -136507,10 +136507,10 @@ index 31bda8da4cb6a56bfe493a81b918900995fb0589..606b2d5012abf2e85712be631c42ea40 }; }; -From 36a11ec05fd2f955b4f38133300f19875f5f1a87 Mon Sep 17 00:00:00 2001 +From f8176778b46646fb0667dc7d2eaf23cb9c46853c Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Tue, 14 Mar 2017 14:23:06 +0000 -Subject: [PATCH 192/205] bcm2835-gpio-exp: Copy/paste error adding base twice +Subject: [PATCH 192/207] bcm2835-gpio-exp: Copy/paste error adding base twice brcmexp_gpio_set was adding gpio->gc.base to the offset twice, so passing an invalid number to the mailbox service. @@ -136536,10 +136536,10 @@ index 681a91492d4c33bdfd42416e069218e8611cc4d9..d68adafaee4ad406f45f4ff0d6b7c1ad set.state = val; /* Output state */ -From 349f0d4c98004520df476c04a7d994222227ac52 Mon Sep 17 00:00:00 2001 +From 7b2dc3ebc96af5f49b83476a955d408b7e773133 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Wed, 15 Mar 2017 11:12:40 +0000 -Subject: [PATCH 193/205] bcm2835-camera: Correct port_parameter_get return +Subject: [PATCH 193/207] bcm2835-camera: Correct port_parameter_get return value The API for port_parameter_get() requires that the @@ -136597,10 +136597,10 @@ index e4b243b33f58913f3d2952c97d2a2e3fbbbd0ae8..ec2853ba9d4b1b0cd6e07a495a424e15 pr_debug("%s:result:%d component:0x%x port:%d parameter:%d\n", __func__, ret, port->component->handle, port->handle, parameter_id); -From 207a9a8733dd04a5d2e636e11b786bf1f9bf9f3d Mon Sep 17 00:00:00 2001 +From 215d0c91534d879cd5e70f09da118567f6e72205 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 17 Mar 2017 12:24:41 +0000 -Subject: [PATCH 194/205] config: Make spidev a loadable module +Subject: [PATCH 194/207] config: Make spidev a loadable module spidev isn't required early in the boot process, and not all users need it (spi_bcm2835 is a module), so make it a loadable module. @@ -136656,10 +136656,10 @@ index efc4898aca911d5c97426a38b0f1808b3c0d4baa..e65b2106d97ea9351c1d85166d2bff39 CONFIG_SND_SIMPLE_CARD=m CONFIG_SOUND_PRIME=m -From d39ab68e32800b114134ce5d3a6c799c96e39423 Mon Sep 17 00:00:00 2001 +From 33d45d5fce66339660a6858ebee0af7f776cd8ed Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 23 Mar 2017 10:06:56 +0000 -Subject: [PATCH 195/205] ASoC: Add prompt for ICS43432 codec +Subject: [PATCH 195/207] ASoC: Add prompt for ICS43432 codec Without a prompt string, a config setting can't be included in a defconfig. Give CONFIG_SND_SOC_ICS43432 a prompt so that Pi soundcards @@ -136684,10 +136684,10 @@ index cd02edde708f860ba90ef7892339ef311c898746..fbcc1516af4f463e5e0a1a8ced04b82c config SND_SOC_INNO_RK3036 tristate "Inno codec driver for RK3036 SoC" -From 7b71cfa31c62d0c70b94edeb14dfa59ae14e903b Mon Sep 17 00:00:00 2001 +From 2cc9b0375a9dae0e3b2773b876a9fc1204a4fdc0 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 23 Mar 2017 16:34:46 +0000 -Subject: [PATCH 196/205] bcm2835-aux: Add aux interrupt controller +Subject: [PATCH 196/207] bcm2835-aux: Add aux interrupt controller The AUX block has a shared interrupt line with a register indicating which devices have active IRQs. Expose this as a nested interrupt @@ -136851,10 +136851,10 @@ index bd750cf2238d61489811e7d7bd3b5f9950ed53c8..41e0702fae4692221980b0d02aed1ba6 BCM2835_AUX_CLOCK_COUNT, GFP_KERNEL); if (!onecell) -From e501ecad1072bc180e1ce90c47addacfed96de5c Mon Sep 17 00:00:00 2001 +From 701211051ea54df90345cbcad012a8f4f710cc1a Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 23 Mar 2017 17:08:44 +0000 -Subject: [PATCH 197/205] BCM270X_DT: Enable AUX interrupt controller in DT +Subject: [PATCH 197/207] BCM270X_DT: Enable AUX interrupt controller in DT See: https://github.com/raspberrypi/linux/issues/1484 https://github.com/raspberrypi/linux/issues/1573 @@ -136907,10 +136907,10 @@ index ee69fd481fabd22d8f45ecdcffacdbb185e11f55..278e7a94a79d01e600f85daa6ec86cd0 #address-cells = <1>; #size-cells = <0>; -From 178e5e6085d6093f9fe9285923216127e1815279 Mon Sep 17 00:00:00 2001 +From c923db3754a1bd66decbcaadc3a4f1316ca88741 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 28 Mar 2017 14:22:20 +0100 -Subject: [PATCH 198/205] BCM270X_DT: Allow multiple instances of w1-gpio +Subject: [PATCH 198/207] BCM270X_DT: Allow multiple instances of w1-gpio overlays Upcoming firmware will modify the address portion of node names when @@ -136975,10 +136975,10 @@ index 66a98f6c9601f51483f27803995bec772bb3350e..ef8bfbcabdb31231075d5c281df3b38b <&w1_pins>,"brcm,pins:4"; pullup = <&w1>,"rpi,parasitic-power:0"; -From 5422d772d134eb455c1fe9927df9373d5c2e755e Mon Sep 17 00:00:00 2001 +From b125f4eba53b70032b26cc99d13ac9dbf4ba8391 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 28 Mar 2017 17:41:30 +0100 -Subject: [PATCH 199/205] leds-gpio: Remove stray assignment to brightness_set +Subject: [PATCH 199/207] leds-gpio: Remove stray assignment to brightness_set The brightness_set method is intended for use cases that must not block, and can only be used if the GPIO provider can never sleep. @@ -137004,10 +137004,10 @@ index 6a27a693034825de2897bb7b338b60cc10c9e59f..a6b352cb003ff5e6c87cf6d37d6502b6 if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP) { state = gpiod_get_value_cansleep(led_dat->gpiod); -From 9b109ee9fdf12c7e33ed89beed25fab81bee580c Mon Sep 17 00:00:00 2001 +From 4c22966f7fa8cdd1c7d8c0ca5bd471b4b2922f9e Mon Sep 17 00:00:00 2001 From: Matt Flax Date: Mon, 27 Mar 2017 22:26:49 +1100 -Subject: [PATCH 200/205] AudioInjector Octo: sample rates, regulators, reset +Subject: [PATCH 200/207] AudioInjector Octo: sample rates, regulators, reset This patch adds new sample rates to the Audioinjector Octo sound card. The new supported rates are (in kHz) : @@ -137173,10 +137173,10 @@ index 9effea725798640887755dfa688da45338718afc..dcf403ab37639ba79e38278d7e4b1ade dai->cpu_dai_name = NULL; dai->cpu_of_node = i2s_node; -From e89ed7afe044ecc9348a1eb4962750ff9589dac1 Mon Sep 17 00:00:00 2001 +From 1463696355c994daaae91ab55853733b4de0aa80 Mon Sep 17 00:00:00 2001 From: Peter Malkin Date: Mon, 27 Mar 2017 16:38:21 -0700 -Subject: [PATCH 201/205] Driver support for Google voiceHAT soundcard. +Subject: [PATCH 201/207] Driver support for Google voiceHAT soundcard. --- arch/arm/boot/dts/overlays/Makefile | 1 + @@ -137681,10 +137681,10 @@ index 0000000000000000000000000000000000000000..225854b8e5298b3c3018f59a49404354 +MODULE_DESCRIPTION("ASoC Driver for Google voiceHAT SoundCard"); +MODULE_LICENSE("GPL v2"); -From 1476b44f72b915f2560f2028f6cabe44323206f9 Mon Sep 17 00:00:00 2001 +From f2f60f6fbd3382abc46200fa66ef030007b4a9e0 Mon Sep 17 00:00:00 2001 From: Raashid Muhammed Date: Mon, 27 Mar 2017 12:35:00 +0530 -Subject: [PATCH 202/205] Add support for Allo Piano DAC 2.1 plus add-on board +Subject: [PATCH 202/207] Add support for Allo Piano DAC 2.1 plus add-on board for Raspberry Pi. The Piano DAC 2.1 has support for 4 channels with subwoofer. @@ -138312,10 +138312,10 @@ index 0000000000000000000000000000000000000000..f66f42abadbd5f9d3fe000676e8297ed +MODULE_DESCRIPTION("ALSA ASoC Machine Driver for Allo Piano DAC Plus"); +MODULE_LICENSE("GPL v2"); -From 2b4910f7fe43fe626198930d0378ddc5a90e7ca0 Mon Sep 17 00:00:00 2001 +From 825769116d94606c88804404423687a0cea4615c Mon Sep 17 00:00:00 2001 From: BabuSubashChandar Date: Tue, 28 Mar 2017 20:04:42 +0530 -Subject: [PATCH 203/205] Add support for Allo Boss DAC add-on board for +Subject: [PATCH 203/207] Add support for Allo Boss DAC add-on board for Raspberry Pi. (#1924) Signed-off-by: Baswaraj K @@ -139045,10 +139045,10 @@ index 0000000000000000000000000000000000000000..c080e31065d99ab309ab3bdf41a44adf +MODULE_DESCRIPTION("ALSA ASoC Machine Driver for Allo Boss DAC"); +MODULE_LICENSE("GPL v2"); -From 8cd4113164673d7421a4575e5486ba269788982d Mon Sep 17 00:00:00 2001 +From 1dca52ea72fdf3e5820d1c3ddb48d88845dfc643 Mon Sep 17 00:00:00 2001 From: BabuSubashChandar C Date: Thu, 30 Mar 2017 20:17:27 +0530 -Subject: [PATCH 204/205] Add support for new clock rate and mute gpios. +Subject: [PATCH 204/207] Add support for new clock rate and mute gpios. Signed-off-by: Baswaraj K Reviewed-by: Deepak @@ -139701,10 +139701,10 @@ index c080e31065d99ab309ab3bdf41a44adfdd8f8039..203ab76c7045b081578e23bda1099dd1 } -From 9305d406ac71a4c9f18a8ff9855156c5f8e341d9 Mon Sep 17 00:00:00 2001 +From 431302fab3a24777fcc66e6870087fdc30a39710 Mon Sep 17 00:00:00 2001 From: BabuSubashChandar Date: Sat, 1 Apr 2017 00:46:52 +0530 -Subject: [PATCH 205/205] Add clock changes and mute gpios (#1938) +Subject: [PATCH 205/207] Add clock changes and mute gpios (#1938) Also improve code style and adhere to ALSA coding conventions. @@ -140396,3 +140396,16237 @@ index f66f42abadbd5f9d3fe000676e8297ed91630e47..56e43f98846b41e487b3089813f7edc3 return snd_soc_unregister_card(&snd_allo_piano_dac); } + +From 490edca292c1570ecd983d6f9638a30705f5625b Mon Sep 17 00:00:00 2001 +From: Yasunari Takiguchi +Date: Fri, 14 Apr 2017 10:43:57 +0100 +Subject: [PATCH 206/207] This is the driver for Sony CXD2880 DVB-T2/T tuner + + demodulator. It includes the CXD2880 driver and the CXD2880 SPI adapter. The + current CXD2880 driver version is 1.4.1 - 1.0.1 released on April 13, 2017. + +Signed-off-by: Yasunari Takiguchi +Signed-off-by: Masayuki Yamamoto +Signed-off-by: Hideki Nozawa +Signed-off-by: Kota Yonezawa +Signed-off-by: Toshihiko Matsumoto +Signed-off-by: Satoshi Watanabe +--- + drivers/media/dvb-frontends/Kconfig | 2 + + drivers/media/dvb-frontends/Makefile | 1 + + drivers/media/dvb-frontends/cxd2880/Kconfig | 6 + + drivers/media/dvb-frontends/cxd2880/Makefile | 21 + + drivers/media/dvb-frontends/cxd2880/cxd2880.h | 46 + + .../media/dvb-frontends/cxd2880/cxd2880_common.c | 84 + + .../media/dvb-frontends/cxd2880/cxd2880_common.h | 86 + + .../dvb-frontends/cxd2880/cxd2880_devio_spi.c | 147 + + .../dvb-frontends/cxd2880/cxd2880_devio_spi.h | 40 + + drivers/media/dvb-frontends/cxd2880/cxd2880_dtv.h | 50 + + drivers/media/dvb-frontends/cxd2880/cxd2880_dvbt.h | 91 + + .../media/dvb-frontends/cxd2880/cxd2880_dvbt2.h | 402 ++ + .../media/dvb-frontends/cxd2880/cxd2880_integ.c | 99 + + .../media/dvb-frontends/cxd2880/cxd2880_integ.h | 44 + + .../dvb-frontends/cxd2880/cxd2880_integ_dvbt.c | 197 + + .../dvb-frontends/cxd2880/cxd2880_integ_dvbt.h | 58 + + .../dvb-frontends/cxd2880/cxd2880_integ_dvbt2.c | 311 ++ + .../dvb-frontends/cxd2880/cxd2880_integ_dvbt2.h | 64 + + drivers/media/dvb-frontends/cxd2880/cxd2880_io.c | 68 + + drivers/media/dvb-frontends/cxd2880/cxd2880_io.h | 62 + + drivers/media/dvb-frontends/cxd2880/cxd2880_math.c | 89 + + drivers/media/dvb-frontends/cxd2880/cxd2880_math.h | 40 + + drivers/media/dvb-frontends/cxd2880/cxd2880_spi.h | 51 + + .../dvb-frontends/cxd2880/cxd2880_spi_device.c | 130 + + .../dvb-frontends/cxd2880/cxd2880_spi_device.h | 45 + + .../media/dvb-frontends/cxd2880/cxd2880_stdlib.h | 35 + + .../dvb-frontends/cxd2880/cxd2880_stopwatch_port.c | 71 + + .../media/dvb-frontends/cxd2880/cxd2880_tnrdmd.c | 3925 ++++++++++++++++++++ + .../media/dvb-frontends/cxd2880/cxd2880_tnrdmd.h | 395 ++ + .../cxd2880/cxd2880_tnrdmd_driver_version.h | 29 + + .../dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt.c | 1072 ++++++ + .../dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt.h | 62 + + .../dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt2.c | 1309 +++++++ + .../dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt2.h | 82 + + .../cxd2880/cxd2880_tnrdmd_dvbt2_mon.c | 2523 +++++++++++++ + .../cxd2880/cxd2880_tnrdmd_dvbt2_mon.h | 170 + + .../cxd2880/cxd2880_tnrdmd_dvbt_mon.c | 1190 ++++++ + .../cxd2880/cxd2880_tnrdmd_dvbt_mon.h | 106 + + .../dvb-frontends/cxd2880/cxd2880_tnrdmd_mon.c | 207 ++ + .../dvb-frontends/cxd2880/cxd2880_tnrdmd_mon.h | 52 + + drivers/media/dvb-frontends/cxd2880/cxd2880_top.c | 1550 ++++++++ + drivers/media/spi/Kconfig | 14 + + drivers/media/spi/Makefile | 5 + + drivers/media/spi/cxd2880-spi.c | 728 ++++ + 44 files changed, 15759 insertions(+) + create mode 100644 drivers/media/dvb-frontends/cxd2880/Kconfig + create mode 100644 drivers/media/dvb-frontends/cxd2880/Makefile + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880.h + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_common.c + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_common.h + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_devio_spi.c + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_devio_spi.h + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_dtv.h + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_dvbt.h + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_dvbt2.h + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_integ.c + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_integ.h + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_integ_dvbt.c + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_integ_dvbt.h + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_integ_dvbt2.c + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_integ_dvbt2.h + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_io.c + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_io.h + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_math.c + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_math.h + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_spi.h + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_spi_device.c + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_spi_device.h + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_stdlib.h + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_stopwatch_port.c + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd.c + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd.h + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_driver_version.h + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt.c + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt.h + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt2.c + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt2.h + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt2_mon.c + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt2_mon.h + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt_mon.c + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt_mon.h + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_mon.c + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_mon.h + create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_top.c + create mode 100644 drivers/media/spi/cxd2880-spi.c + +diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig +index c841fa1770bec376559d3292f262b41b3a78d5bb..7b6dee771df2680c0db1a500a45cce2711a88991 100644 +--- a/drivers/media/dvb-frontends/Kconfig ++++ b/drivers/media/dvb-frontends/Kconfig +@@ -518,6 +518,8 @@ config DVB_GP8PSK_FE + depends on DVB_CORE + default DVB_USB_GP8PSK + ++source "drivers/media/dvb-frontends/cxd2880/Kconfig" ++ + comment "DVB-C (cable) frontends" + depends on DVB_CORE + +diff --git a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile +index 93921a4eaa275997a5ed4178de1acb1a54409430..5629631ffb2f044363fd1e1d820e4df75ec41c2b 100644 +--- a/drivers/media/dvb-frontends/Makefile ++++ b/drivers/media/dvb-frontends/Makefile +@@ -126,3 +126,4 @@ obj-$(CONFIG_DVB_TC90522) += tc90522.o + obj-$(CONFIG_DVB_HORUS3A) += horus3a.o + obj-$(CONFIG_DVB_ASCOT2E) += ascot2e.o + obj-$(CONFIG_DVB_HELENE) += helene.o ++obj-$(CONFIG_DVB_CXD2880) += cxd2880/ +diff --git a/drivers/media/dvb-frontends/cxd2880/Kconfig b/drivers/media/dvb-frontends/cxd2880/Kconfig +new file mode 100644 +index 0000000000000000000000000000000000000000..36b8b6f7c4f71d9b0b8539c2713e800a32913d8e +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/Kconfig +@@ -0,0 +1,6 @@ ++config DVB_CXD2880 ++ tristate "Sony CXD2880 DVB-T2/T tuner + demodulator" ++ depends on DVB_CORE && SPI ++ default m if !MEDIA_SUBDRV_AUTOSELECT ++ help ++ Say Y when you want to support this frontend. +\ No newline at end of file +diff --git a/drivers/media/dvb-frontends/cxd2880/Makefile b/drivers/media/dvb-frontends/cxd2880/Makefile +new file mode 100644 +index 0000000000000000000000000000000000000000..2672c4a3d65cf4ff65e9dc8d240ae88cdfa1eb19 +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/Makefile +@@ -0,0 +1,21 @@ ++cxd2880-objs := cxd2880_common.o \ ++ cxd2880_devio_spi.o \ ++ cxd2880_integ.o \ ++ cxd2880_integ_dvbt2.o \ ++ cxd2880_integ_dvbt.o \ ++ cxd2880_io.o \ ++ cxd2880_spi_device.o \ ++ cxd2880_stopwatch_port.o \ ++ cxd2880_tnrdmd.o \ ++ cxd2880_tnrdmd_dvbt2.o \ ++ cxd2880_tnrdmd_dvbt2_mon.o \ ++ cxd2880_tnrdmd_dvbt.o \ ++ cxd2880_tnrdmd_dvbt_mon.o\ ++ cxd2880_tnrdmd_mon.o\ ++ cxd2880_math.o \ ++ cxd2880_top.o ++ ++obj-$(CONFIG_DVB_CXD2880) += cxd2880.o ++ ++ccflags-y += -Idrivers/media/dvb-core ++ccflags-y += -Idrivers/media/dvb-frontends +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880.h b/drivers/media/dvb-frontends/cxd2880/cxd2880.h +new file mode 100644 +index 0000000000000000000000000000000000000000..281f9a784eb530355bcf94500609d17180b9f73c +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880.h +@@ -0,0 +1,46 @@ ++/* ++ * cxd2880.h ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver public definitions ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#ifndef CXD2880_H ++#define CXD2880_H ++ ++struct cxd2880_config { ++ struct spi_device *spi; ++ struct mutex *spi_mutex; /* For SPI access exclusive control */ ++}; ++ ++#if IS_REACHABLE(CONFIG_DVB_CXD2880) ++extern struct dvb_frontend *cxd2880_attach(struct dvb_frontend *fe, ++ struct cxd2880_config *cfg); ++#else ++static inline struct dvb_frontend *cxd2880_attach(struct dvb_frontend *fe, ++ struct cxd2880_config *cfg) ++{ ++ pr_warn("%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++#endif /* CONFIG_DVB_CXD2880 */ ++ ++#endif /* CXD2880_H */ +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_common.c b/drivers/media/dvb-frontends/cxd2880/cxd2880_common.c +new file mode 100644 +index 0000000000000000000000000000000000000000..850f3a76b2c79808fd080801507f8edcda5d4b4d +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_common.c +@@ -0,0 +1,84 @@ ++/* ++ * cxd2880_common.c ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * common functions ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#include "cxd2880_common.h" ++ ++#define MASKUPPER(n) (((n) == 0) ? 0 : (0xFFFFFFFFU << (32 - (n)))) ++#define MASKLOWER(n) (((n) == 0) ? 0 : (0xFFFFFFFFU >> (32 - (n)))) ++ ++int cxd2880_convert2s_complement(u32 value, u32 bitlen) ++{ ++ if ((bitlen == 0) || (bitlen >= 32)) ++ return (int)value; ++ ++ if (value & (u32)(1 << (bitlen - 1))) ++ return (int)(MASKUPPER(32 - bitlen) | value); ++ else ++ return (int)(MASKLOWER(bitlen) & value); ++} ++ ++u32 cxd2880_bit_split_from_byte_array(u8 *array, u32 start_bit, u32 bit_num) ++{ ++ u32 value = 0; ++ u8 *array_read; ++ u8 bit_read; ++ u32 len_remain; ++ ++ if (!array) ++ return 0; ++ if ((bit_num == 0) || (bit_num > 32)) ++ return 0; ++ ++ array_read = array + (start_bit / 8); ++ bit_read = (u8)(start_bit % 8); ++ len_remain = bit_num; ++ ++ if (bit_read != 0) { ++ if (((int)len_remain) <= 8 - bit_read) { ++ value = (*array_read) >> ((8 - bit_read) - len_remain); ++ len_remain = 0; ++ } else { ++ value = *array_read++; ++ len_remain -= 8 - bit_read; ++ } ++ } ++ ++ while (len_remain > 0) { ++ if (len_remain < 8) { ++ value <<= len_remain; ++ value |= (*array_read++ >> (8 - len_remain)); ++ len_remain = 0; ++ } else { ++ value <<= 8; ++ value |= (u32)(*array_read++); ++ len_remain -= 8; ++ } ++ } ++ ++ value &= MASKLOWER(bit_num); ++ ++ return value; ++} +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_common.h b/drivers/media/dvb-frontends/cxd2880/cxd2880_common.h +new file mode 100644 +index 0000000000000000000000000000000000000000..b1ecb44bca10f730b1dc6add663c469ade5784c9 +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_common.h +@@ -0,0 +1,86 @@ ++/* ++ * cxd2880_common.h ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver common definitions ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#ifndef CXD2880_COMMON_H ++#define CXD2880_COMMON_H ++ ++#include ++ ++#ifndef NULL ++#ifdef __cplusplus ++#define NULL 0 ++#else ++#define NULL ((void *)0) ++#endif ++#endif ++ ++#include ++#define CXD2880_SLEEP(n) msleep(n) ++#ifndef CXD2880_SLEEP_IN_MON ++#define CXD2880_SLEEP_IN_MON(n, obj) CXD2880_SLEEP(n) ++#endif ++ ++#define CXD2880_ARG_UNUSED(arg) ((void)(arg)) ++ ++enum cxd2880_ret { ++ CXD2880_RESULT_OK, ++ CXD2880_RESULT_ERROR_ARG, ++ CXD2880_RESULT_ERROR_IO, ++ CXD2880_RESULT_ERROR_SW_STATE, ++ CXD2880_RESULT_ERROR_HW_STATE, ++ CXD2880_RESULT_ERROR_TIMEOUT, ++ CXD2880_RESULT_ERROR_UNLOCK, ++ CXD2880_RESULT_ERROR_RANGE, ++ CXD2880_RESULT_ERROR_NOSUPPORT, ++ CXD2880_RESULT_ERROR_CANCEL, ++ CXD2880_RESULT_ERROR_OTHER, ++ CXD2880_RESULT_ERROR_OVERFLOW, ++ CXD2880_RESULT_OK_CONFIRM ++}; ++ ++int cxd2880_convert2s_complement(u32 value, u32 bitlen); ++ ++u32 cxd2880_bit_split_from_byte_array(u8 *array, u32 start_bit, u32 bit_num); ++ ++struct cxd2880_atomic { ++ int counter; ++}; ++ ++#define cxd2880_atomic_set(a, i) ((a)->counter = i) ++#define cxd2880_atomic_read(a) ((a)->counter) ++ ++struct cxd2880_stopwatch { ++ u32 start_time; ++}; ++ ++enum cxd2880_ret cxd2880_stopwatch_start(struct cxd2880_stopwatch *stopwatch); ++ ++enum cxd2880_ret cxd2880_stopwatch_sleep(struct cxd2880_stopwatch *stopwatch, ++ u32 ms); ++ ++enum cxd2880_ret cxd2880_stopwatch_elapsed(struct cxd2880_stopwatch *stopwatch, ++ u32 *elapsed); ++ ++#endif +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_devio_spi.c b/drivers/media/dvb-frontends/cxd2880/cxd2880_devio_spi.c +new file mode 100644 +index 0000000000000000000000000000000000000000..516efade6bf586629f5df6a72e7cd0f81544ee90 +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_devio_spi.c +@@ -0,0 +1,147 @@ ++/* ++ * cxd2880_devio_spi.c ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * I/O interface via SPI ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#include "cxd2880_devio_spi.h" ++#include "cxd2880_stdlib.h" ++ ++#define BURST_WRITE_MAX 128 ++ ++static enum cxd2880_ret cxd2880_io_spi_read_reg(struct cxd2880_io *io, ++ enum cxd2880_io_tgt tgt, ++ u8 sub_address, u8 *data, ++ u32 size) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ struct cxd2880_spi *spi = NULL; ++ u8 send_data[6]; ++ u8 *read_data_top = data; ++ ++ if ((!io) || (!io->if_object) || (!data)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (sub_address + size > 0x100) ++ return CXD2880_RESULT_ERROR_RANGE; ++ ++ spi = (struct cxd2880_spi *)(io->if_object); ++ ++ if (tgt == CXD2880_IO_TGT_SYS) ++ send_data[0] = 0x0B; ++ else ++ send_data[0] = 0x0A; ++ ++ send_data[3] = 0; ++ send_data[4] = 0; ++ send_data[5] = 0; ++ ++ while (size > 0) { ++ send_data[1] = sub_address; ++ if (size > 255) ++ send_data[2] = 255; ++ else ++ send_data[2] = (u8)size; ++ ++ ret = ++ spi->write_read(spi, send_data, sizeof(send_data), ++ read_data_top, send_data[2]); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ sub_address += send_data[2]; ++ read_data_top += send_data[2]; ++ size -= send_data[2]; ++ } ++ ++ return ret; ++} ++ ++static enum cxd2880_ret cxd2880_io_spi_write_reg(struct cxd2880_io *io, ++ enum cxd2880_io_tgt tgt, ++ u8 sub_address, ++ const u8 *data, u32 size) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ struct cxd2880_spi *spi = NULL; ++ u8 send_data[BURST_WRITE_MAX + 4]; ++ const u8 *write_data_top = data; ++ ++ if ((!io) || (!io->if_object) || (!data)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (size > BURST_WRITE_MAX) ++ return CXD2880_RESULT_ERROR_OVERFLOW; ++ ++ if (sub_address + size > 0x100) ++ return CXD2880_RESULT_ERROR_RANGE; ++ ++ spi = (struct cxd2880_spi *)(io->if_object); ++ ++ if (tgt == CXD2880_IO_TGT_SYS) ++ send_data[0] = 0x0F; ++ else ++ send_data[0] = 0x0E; ++ ++ while (size > 0) { ++ send_data[1] = sub_address; ++ if (size > 255) ++ send_data[2] = 255; ++ else ++ send_data[2] = (u8)size; ++ ++ cxd2880_memcpy(&send_data[3], write_data_top, send_data[2]); ++ ++ if (tgt == CXD2880_IO_TGT_SYS) { ++ send_data[3 + send_data[2]] = 0x00; ++ ret = spi->write(spi, send_data, send_data[2] + 4); ++ } else { ++ ret = spi->write(spi, send_data, send_data[2] + 3); ++ } ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ sub_address += send_data[2]; ++ write_data_top += send_data[2]; ++ size -= send_data[2]; ++ } ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_io_spi_create(struct cxd2880_io *io, ++ struct cxd2880_spi *spi, u8 slave_select) ++{ ++ if ((!io) || (!spi)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ io->read_regs = cxd2880_io_spi_read_reg; ++ io->write_regs = cxd2880_io_spi_write_reg; ++ io->write_reg = cxd2880_io_common_write_one_reg; ++ io->if_object = spi; ++ io->i2c_address_sys = 0; ++ io->i2c_address_demod = 0; ++ io->slave_select = slave_select; ++ ++ return CXD2880_RESULT_OK; ++} +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_devio_spi.h b/drivers/media/dvb-frontends/cxd2880/cxd2880_devio_spi.h +new file mode 100644 +index 0000000000000000000000000000000000000000..15934bf11935bb0da08996f3441891fb8710b15c +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_devio_spi.h +@@ -0,0 +1,40 @@ ++/* ++ * cxd2880_devio_spi.h ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * I/O interface via SPI ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#ifndef CXD2880_DEVIO_SPI_H ++#define CXD2880_DEVIO_SPI_H ++ ++#include "cxd2880_common.h" ++#include "cxd2880_io.h" ++#include "cxd2880_spi.h" ++ ++#include "cxd2880_tnrdmd.h" ++ ++enum cxd2880_ret cxd2880_io_spi_create(struct cxd2880_io *io, ++ struct cxd2880_spi *spi, ++ u8 slave_select); ++ ++#endif +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_dtv.h b/drivers/media/dvb-frontends/cxd2880/cxd2880_dtv.h +new file mode 100644 +index 0000000000000000000000000000000000000000..7de098d556fec6a90f7335328059de4c69d66df2 +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_dtv.h +@@ -0,0 +1,50 @@ ++/* ++ * cxd2880_dtv.h ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * DTV related definitions ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#ifndef CXD2880_DTV_H ++#define CXD2880_DTV_H ++ ++enum cxd2880_dtv_sys { ++ CXD2880_DTV_SYS_UNKNOWN, ++ CXD2880_DTV_SYS_DVBT, ++ CXD2880_DTV_SYS_DVBT2, ++ CXD2880_DTV_SYS_ISDBT, ++ CXD2880_DTV_SYS_ISDBTSB, ++ CXD2880_DTV_SYS_ISDBTMM_A, ++ CXD2880_DTV_SYS_ISDBTMM_B, ++ CXD2880_DTV_SYS_ANY ++}; ++ ++enum cxd2880_dtv_bandwidth { ++ CXD2880_DTV_BW_UNKNOWN = 0, ++ CXD2880_DTV_BW_1_7_MHZ = 1, ++ CXD2880_DTV_BW_5_MHZ = 5, ++ CXD2880_DTV_BW_6_MHZ = 6, ++ CXD2880_DTV_BW_7_MHZ = 7, ++ CXD2880_DTV_BW_8_MHZ = 8 ++}; ++ ++#endif +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_dvbt.h b/drivers/media/dvb-frontends/cxd2880/cxd2880_dvbt.h +new file mode 100644 +index 0000000000000000000000000000000000000000..345c094760d28a48995aca91b61ff034fa475db0 +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_dvbt.h +@@ -0,0 +1,91 @@ ++/* ++ * cxd2880_dvbt.h ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * DVB-T related definitions ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#ifndef CXD2880_DVBT_H ++#define CXD2880_DVBT_H ++ ++#include "cxd2880_common.h" ++ ++enum cxd2880_dvbt_constellation { ++ CXD2880_DVBT_CONSTELLATION_QPSK, ++ CXD2880_DVBT_CONSTELLATION_16QAM, ++ CXD2880_DVBT_CONSTELLATION_64QAM, ++ CXD2880_DVBT_CONSTELLATION_RESERVED_3 ++}; ++ ++enum cxd2880_dvbt_hierarchy { ++ CXD2880_DVBT_HIERARCHY_NON, ++ CXD2880_DVBT_HIERARCHY_1, ++ CXD2880_DVBT_HIERARCHY_2, ++ CXD2880_DVBT_HIERARCHY_4 ++}; ++ ++enum cxd2880_dvbt_coderate { ++ CXD2880_DVBT_CODERATE_1_2, ++ CXD2880_DVBT_CODERATE_2_3, ++ CXD2880_DVBT_CODERATE_3_4, ++ CXD2880_DVBT_CODERATE_5_6, ++ CXD2880_DVBT_CODERATE_7_8, ++ CXD2880_DVBT_CODERATE_RESERVED_5, ++ CXD2880_DVBT_CODERATE_RESERVED_6, ++ CXD2880_DVBT_CODERATE_RESERVED_7 ++}; ++ ++enum cxd2880_dvbt_guard { ++ CXD2880_DVBT_GUARD_1_32, ++ CXD2880_DVBT_GUARD_1_16, ++ CXD2880_DVBT_GUARD_1_8, ++ CXD2880_DVBT_GUARD_1_4 ++}; ++ ++enum cxd2880_dvbt_mode { ++ CXD2880_DVBT_MODE_2K, ++ CXD2880_DVBT_MODE_8K, ++ CXD2880_DVBT_MODE_RESERVED_2, ++ CXD2880_DVBT_MODE_RESERVED_3 ++}; ++ ++enum cxd2880_dvbt_profile { ++ CXD2880_DVBT_PROFILE_HP = 0, ++ CXD2880_DVBT_PROFILE_LP ++}; ++ ++struct cxd2880_dvbt_tpsinfo { ++ enum cxd2880_dvbt_constellation constellation; ++ enum cxd2880_dvbt_hierarchy hierarchy; ++ enum cxd2880_dvbt_coderate rate_hp; ++ enum cxd2880_dvbt_coderate rate_lp; ++ enum cxd2880_dvbt_guard guard; ++ enum cxd2880_dvbt_mode mode; ++ u8 fnum; ++ u8 length_indicator; ++ u16 cell_id; ++ u8 cell_id_ok; ++ u8 reserved_even; ++ u8 reserved_odd; ++}; ++ ++#endif +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_dvbt2.h b/drivers/media/dvb-frontends/cxd2880/cxd2880_dvbt2.h +new file mode 100644 +index 0000000000000000000000000000000000000000..1870398cba9da50143a0c0d0774763edd8a31e78 +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_dvbt2.h +@@ -0,0 +1,402 @@ ++/* ++ * cxd2880_dvbt2.h ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * DVB-T2 related definitions ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#ifndef CXD2880_DVBT2_H ++#define CXD2880_DVBT2_H ++ ++#include "cxd2880_common.h" ++ ++enum cxd2880_dvbt2_profile { ++ CXD2880_DVBT2_PROFILE_BASE, ++ CXD2880_DVBT2_PROFILE_LITE, ++ CXD2880_DVBT2_PROFILE_ANY ++}; ++ ++enum cxd2880_dvbt2_version { ++ CXD2880_DVBT2_V111, ++ CXD2880_DVBT2_V121, ++ CXD2880_DVBT2_V131 ++}; ++ ++enum cxd2880_dvbt2_s1 { ++ CXD2880_DVBT2_S1_BASE_SISO = 0x00, ++ CXD2880_DVBT2_S1_BASE_MISO = 0x01, ++ CXD2880_DVBT2_S1_NON_DVBT2 = 0x02, ++ CXD2880_DVBT2_S1_LITE_SISO = 0x03, ++ CXD2880_DVBT2_S1_LITE_MISO = 0x04, ++ CXD2880_DVBT2_S1_RSVD3 = 0x05, ++ CXD2880_DVBT2_S1_RSVD4 = 0x06, ++ CXD2880_DVBT2_S1_RSVD5 = 0x07, ++ CXD2880_DVBT2_S1_UNKNOWN = 0xFF ++}; ++ ++enum cxd2880_dvbt2_base_s2 { ++ CXD2880_DVBT2_BASE_S2_M2K_G_ANY = 0x00, ++ CXD2880_DVBT2_BASE_S2_M8K_G_DVBT = 0x01, ++ CXD2880_DVBT2_BASE_S2_M4K_G_ANY = 0x02, ++ CXD2880_DVBT2_BASE_S2_M1K_G_ANY = 0x03, ++ CXD2880_DVBT2_BASE_S2_M16K_G_ANY = 0x04, ++ CXD2880_DVBT2_BASE_S2_M32K_G_DVBT = 0x05, ++ CXD2880_DVBT2_BASE_S2_M8K_G_DVBT2 = 0x06, ++ CXD2880_DVBT2_BASE_S2_M32K_G_DVBT2 = 0x07, ++ CXD2880_DVBT2_BASE_S2_UNKNOWN = 0xFF ++}; ++ ++enum cxd2880_dvbt2_lite_s2 { ++ CXD2880_DVBT2_LITE_S2_M2K_G_ANY = 0x00, ++ CXD2880_DVBT2_LITE_S2_M8K_G_DVBT = 0x01, ++ CXD2880_DVBT2_LITE_S2_M4K_G_ANY = 0x02, ++ CXD2880_DVBT2_LITE_S2_M16K_G_DVBT2 = 0x03, ++ CXD2880_DVBT2_LITE_S2_M16K_G_DVBT = 0x04, ++ CXD2880_DVBT2_LITE_S2_RSVD1 = 0x05, ++ CXD2880_DVBT2_LITE_S2_M8K_G_DVBT2 = 0x06, ++ CXD2880_DVBT2_LITE_S2_RSVD2 = 0x07, ++ CXD2880_DVBT2_LITE_S2_UNKNOWN = 0xFF ++}; ++ ++enum cxd2880_dvbt2_guard { ++ CXD2880_DVBT2_G1_32 = 0x00, ++ CXD2880_DVBT2_G1_16 = 0x01, ++ CXD2880_DVBT2_G1_8 = 0x02, ++ CXD2880_DVBT2_G1_4 = 0x03, ++ CXD2880_DVBT2_G1_128 = 0x04, ++ CXD2880_DVBT2_G19_128 = 0x05, ++ CXD2880_DVBT2_G19_256 = 0x06, ++ CXD2880_DVBT2_G_RSVD1 = 0x07, ++ CXD2880_DVBT2_G_UNKNOWN = 0xFF ++}; ++ ++enum cxd2880_dvbt2_mode { ++ CXD2880_DVBT2_M2K = 0x00, ++ CXD2880_DVBT2_M8K = 0x01, ++ CXD2880_DVBT2_M4K = 0x02, ++ CXD2880_DVBT2_M1K = 0x03, ++ CXD2880_DVBT2_M16K = 0x04, ++ CXD2880_DVBT2_M32K = 0x05, ++ CXD2880_DVBT2_M_RSVD1 = 0x06, ++ CXD2880_DVBT2_M_RSVD2 = 0x07 ++}; ++ ++enum cxd2880_dvbt2_bw { ++ CXD2880_DVBT2_BW_8 = 0x00, ++ CXD2880_DVBT2_BW_7 = 0x01, ++ CXD2880_DVBT2_BW_6 = 0x02, ++ CXD2880_DVBT2_BW_5 = 0x03, ++ CXD2880_DVBT2_BW_10 = 0x04, ++ CXD2880_DVBT2_BW_1_7 = 0x05, ++ CXD2880_DVBT2_BW_RSVD1 = 0x06, ++ CXD2880_DVBT2_BW_RSVD2 = 0x07, ++ CXD2880_DVBT2_BW_RSVD3 = 0x08, ++ CXD2880_DVBT2_BW_RSVD4 = 0x09, ++ CXD2880_DVBT2_BW_RSVD5 = 0x0A, ++ CXD2880_DVBT2_BW_RSVD6 = 0x0B, ++ CXD2880_DVBT2_BW_RSVD7 = 0x0C, ++ CXD2880_DVBT2_BW_RSVD8 = 0x0D, ++ CXD2880_DVBT2_BW_RSVD9 = 0x0E, ++ CXD2880_DVBT2_BW_RSVD10 = 0x0F, ++ CXD2880_DVBT2_BW_UNKNOWN = 0xFF ++}; ++ ++enum cxd2880_dvbt2_l1pre_type { ++ CXD2880_DVBT2_L1PRE_TYPE_TS = 0x00, ++ CXD2880_DVBT2_L1PRE_TYPE_GS = 0x01, ++ CXD2880_DVBT2_L1PRE_TYPE_TS_GS = 0x02, ++ CXD2880_DVBT2_L1PRE_TYPE_RESERVED = 0x03, ++ CXD2880_DVBT2_L1PRE_TYPE_UNKNOWN = 0xFF ++}; ++ ++enum cxd2880_dvbt2_papr { ++ CXD2880_DVBT2_PAPR_0 = 0x00, ++ CXD2880_DVBT2_PAPR_1 = 0x01, ++ CXD2880_DVBT2_PAPR_2 = 0x02, ++ CXD2880_DVBT2_PAPR_3 = 0x03, ++ CXD2880_DVBT2_PAPR_RSVD1 = 0x04, ++ CXD2880_DVBT2_PAPR_RSVD2 = 0x05, ++ CXD2880_DVBT2_PAPR_RSVD3 = 0x06, ++ CXD2880_DVBT2_PAPR_RSVD4 = 0x07, ++ CXD2880_DVBT2_PAPR_RSVD5 = 0x08, ++ CXD2880_DVBT2_PAPR_RSVD6 = 0x09, ++ CXD2880_DVBT2_PAPR_RSVD7 = 0x0A, ++ CXD2880_DVBT2_PAPR_RSVD8 = 0x0B, ++ CXD2880_DVBT2_PAPR_RSVD9 = 0x0C, ++ CXD2880_DVBT2_PAPR_RSVD10 = 0x0D, ++ CXD2880_DVBT2_PAPR_RSVD11 = 0x0E, ++ CXD2880_DVBT2_PAPR_RSVD12 = 0x0F, ++ CXD2880_DVBT2_PAPR_UNKNOWN = 0xFF ++}; ++ ++enum cxd2880_dvbt2_l1post_constell { ++ CXD2880_DVBT2_L1POST_BPSK = 0x00, ++ CXD2880_DVBT2_L1POST_QPSK = 0x01, ++ CXD2880_DVBT2_L1POST_QAM16 = 0x02, ++ CXD2880_DVBT2_L1POST_QAM64 = 0x03, ++ CXD2880_DVBT2_L1POST_C_RSVD1 = 0x04, ++ CXD2880_DVBT2_L1POST_C_RSVD2 = 0x05, ++ CXD2880_DVBT2_L1POST_C_RSVD3 = 0x06, ++ CXD2880_DVBT2_L1POST_C_RSVD4 = 0x07, ++ CXD2880_DVBT2_L1POST_C_RSVD5 = 0x08, ++ CXD2880_DVBT2_L1POST_C_RSVD6 = 0x09, ++ CXD2880_DVBT2_L1POST_C_RSVD7 = 0x0A, ++ CXD2880_DVBT2_L1POST_C_RSVD8 = 0x0B, ++ CXD2880_DVBT2_L1POST_C_RSVD9 = 0x0C, ++ CXD2880_DVBT2_L1POST_C_RSVD10 = 0x0D, ++ CXD2880_DVBT2_L1POST_C_RSVD11 = 0x0E, ++ CXD2880_DVBT2_L1POST_C_RSVD12 = 0x0F, ++ CXD2880_DVBT2_L1POST_CONSTELL_UNKNOWN = 0xFF ++}; ++ ++enum cxd2880_dvbt2_l1post_cr { ++ CXD2880_DVBT2_L1POST_R1_2 = 0x00, ++ CXD2880_DVBT2_L1POST_R_RSVD1 = 0x01, ++ CXD2880_DVBT2_L1POST_R_RSVD2 = 0x02, ++ CXD2880_DVBT2_L1POST_R_RSVD3 = 0x03, ++ CXD2880_DVBT2_L1POST_R_UNKNOWN = 0xFF ++}; ++ ++enum cxd2880_dvbt2_l1post_fec_type { ++ CXD2880_DVBT2_L1POST_FEC_LDPC16K = 0x00, ++ CXD2880_DVBT2_L1POST_FEC_RSVD1 = 0x01, ++ CXD2880_DVBT2_L1POST_FEC_RSVD2 = 0x02, ++ CXD2880_DVBT2_L1POST_FEC_RSVD3 = 0x03, ++ CXD2880_DVBT2_L1POST_FEC_UNKNOWN = 0xFF ++}; ++ ++enum cxd2880_dvbt2_pp { ++ CXD2880_DVBT2_PP1 = 0x00, ++ CXD2880_DVBT2_PP2 = 0x01, ++ CXD2880_DVBT2_PP3 = 0x02, ++ CXD2880_DVBT2_PP4 = 0x03, ++ CXD2880_DVBT2_PP5 = 0x04, ++ CXD2880_DVBT2_PP6 = 0x05, ++ CXD2880_DVBT2_PP7 = 0x06, ++ CXD2880_DVBT2_PP8 = 0x07, ++ CXD2880_DVBT2_PP_RSVD1 = 0x08, ++ CXD2880_DVBT2_PP_RSVD2 = 0x09, ++ CXD2880_DVBT2_PP_RSVD3 = 0x0A, ++ CXD2880_DVBT2_PP_RSVD4 = 0x0B, ++ CXD2880_DVBT2_PP_RSVD5 = 0x0C, ++ CXD2880_DVBT2_PP_RSVD6 = 0x0D, ++ CXD2880_DVBT2_PP_RSVD7 = 0x0E, ++ CXD2880_DVBT2_PP_RSVD8 = 0x0F, ++ CXD2880_DVBT2_PP_UNKNOWN = 0xFF ++}; ++ ++enum cxd2880_dvbt2_plp_code_rate { ++ CXD2880_DVBT2_R1_2 = 0x00, ++ CXD2880_DVBT2_R3_5 = 0x01, ++ CXD2880_DVBT2_R2_3 = 0x02, ++ CXD2880_DVBT2_R3_4 = 0x03, ++ CXD2880_DVBT2_R4_5 = 0x04, ++ CXD2880_DVBT2_R5_6 = 0x05, ++ CXD2880_DVBT2_R1_3 = 0x06, ++ CXD2880_DVBT2_R2_5 = 0x07, ++ CXD2880_DVBT2_PLP_CR_UNKNOWN = 0xFF ++}; ++ ++enum cxd2880_dvbt2_plp_constell { ++ CXD2880_DVBT2_QPSK = 0x00, ++ CXD2880_DVBT2_QAM16 = 0x01, ++ CXD2880_DVBT2_QAM64 = 0x02, ++ CXD2880_DVBT2_QAM256 = 0x03, ++ CXD2880_DVBT2_CON_RSVD1 = 0x04, ++ CXD2880_DVBT2_CON_RSVD2 = 0x05, ++ CXD2880_DVBT2_CON_RSVD3 = 0x06, ++ CXD2880_DVBT2_CON_RSVD4 = 0x07, ++ CXD2880_DVBT2_CONSTELL_UNKNOWN = 0xFF ++}; ++ ++enum cxd2880_dvbt2_plp_type { ++ CXD2880_DVBT2_PLP_TYPE_COMMON = 0x00, ++ CXD2880_DVBT2_PLP_TYPE_DATA1 = 0x01, ++ CXD2880_DVBT2_PLP_TYPE_DATA2 = 0x02, ++ CXD2880_DVBT2_PLP_TYPE_RSVD1 = 0x03, ++ CXD2880_DVBT2_PLP_TYPE_RSVD2 = 0x04, ++ CXD2880_DVBT2_PLP_TYPE_RSVD3 = 0x05, ++ CXD2880_DVBT2_PLP_TYPE_RSVD4 = 0x06, ++ CXD2880_DVBT2_PLP_TYPE_RSVD5 = 0x07, ++ CXD2880_DVBT2_PLP_TYPE_UNKNOWN = 0xFF ++}; ++ ++enum cxd2880_dvbt2_plp_payload { ++ CXD2880_DVBT2_PLP_PAYLOAD_GFPS = 0x00, ++ CXD2880_DVBT2_PLP_PAYLOAD_GCS = 0x01, ++ CXD2880_DVBT2_PLP_PAYLOAD_GSE = 0x02, ++ CXD2880_DVBT2_PLP_PAYLOAD_TS = 0x03, ++ CXD2880_DVBT2_PLP_PAYLOAD_RSVD1 = 0x04, ++ CXD2880_DVBT2_PLP_PAYLOAD_RSVD2 = 0x05, ++ CXD2880_DVBT2_PLP_PAYLOAD_RSVD3 = 0x06, ++ CXD2880_DVBT2_PLP_PAYLOAD_RSVD4 = 0x07, ++ CXD2880_DVBT2_PLP_PAYLOAD_RSVD5 = 0x08, ++ CXD2880_DVBT2_PLP_PAYLOAD_RSVD6 = 0x09, ++ CXD2880_DVBT2_PLP_PAYLOAD_RSVD7 = 0x0A, ++ CXD2880_DVBT2_PLP_PAYLOAD_RSVD8 = 0x0B, ++ CXD2880_DVBT2_PLP_PAYLOAD_RSVD9 = 0x0C, ++ CXD2880_DVBT2_PLP_PAYLOAD_RSVD10 = 0x0D, ++ CXD2880_DVBT2_PLP_PAYLOAD_RSVD11 = 0x0E, ++ CXD2880_DVBT2_PLP_PAYLOAD_RSVD12 = 0x0F, ++ CXD2880_DVBT2_PLP_PAYLOAD_RSVD13 = 0x10, ++ CXD2880_DVBT2_PLP_PAYLOAD_RSVD14 = 0x11, ++ CXD2880_DVBT2_PLP_PAYLOAD_RSVD15 = 0x12, ++ CXD2880_DVBT2_PLP_PAYLOAD_RSVD16 = 0x13, ++ CXD2880_DVBT2_PLP_PAYLOAD_RSVD17 = 0x14, ++ CXD2880_DVBT2_PLP_PAYLOAD_RSVD18 = 0x15, ++ CXD2880_DVBT2_PLP_PAYLOAD_RSVD19 = 0x16, ++ CXD2880_DVBT2_PLP_PAYLOAD_RSVD20 = 0x17, ++ CXD2880_DVBT2_PLP_PAYLOAD_RSVD21 = 0x18, ++ CXD2880_DVBT2_PLP_PAYLOAD_RSVD22 = 0x19, ++ CXD2880_DVBT2_PLP_PAYLOAD_RSVD23 = 0x1A, ++ CXD2880_DVBT2_PLP_PAYLOAD_RSVD24 = 0x1B, ++ CXD2880_DVBT2_PLP_PAYLOAD_RSVD25 = 0x1C, ++ CXD2880_DVBT2_PLP_PAYLOAD_RSVD26 = 0x1D, ++ CXD2880_DVBT2_PLP_PAYLOAD_RSVD27 = 0x1E, ++ CXD2880_DVBT2_PLP_PAYLOAD_RSVD28 = 0x1F, ++ CXD2880_DVBT2_PLP_PAYLOAD_UNKNOWN = 0xFF ++}; ++ ++enum cxd2880_dvbt2_plp_fec { ++ CXD2880_DVBT2_FEC_LDPC_16K = 0x00, ++ CXD2880_DVBT2_FEC_LDPC_64K = 0x01, ++ CXD2880_DVBT2_FEC_RSVD1 = 0x02, ++ CXD2880_DVBT2_FEC_RSVD2 = 0x03, ++ CXD2880_DVBT2_FEC_UNKNOWN = 0xFF ++}; ++ ++enum cxd2880_dvbt2_plp_mode { ++ CXD2880_DVBT2_PLP_MODE_NOTSPECIFIED = 0x00, ++ CXD2880_DVBT2_PLP_MODE_NM = 0x01, ++ CXD2880_DVBT2_PLP_MODE_HEM = 0x02, ++ CXD2880_DVBT2_PLP_MODE_RESERVED = 0x03, ++ CXD2880_DVBT2_PLP_MODE_UNKNOWN = 0xFF ++}; ++ ++enum cxd2880_dvbt2_plp_btype { ++ CXD2880_DVBT2_PLP_COMMON, ++ CXD2880_DVBT2_PLP_DATA ++}; ++ ++enum cxd2880_dvbt2_stream { ++ CXD2880_DVBT2_STREAM_GENERIC_PACKETIZED = 0x00, ++ CXD2880_DVBT2_STREAM_GENERIC_CONTINUOUS = 0x01, ++ CXD2880_DVBT2_STREAM_GENERIC_ENCAPSULATED = 0x02, ++ CXD2880_DVBT2_STREAM_TRANSPORT = 0x03, ++ CXD2880_DVBT2_STREAM_UNKNOWN = 0xFF ++}; ++ ++struct cxd2880_dvbt2_l1pre { ++ enum cxd2880_dvbt2_l1pre_type type; ++ u8 bw_ext; ++ enum cxd2880_dvbt2_s1 s1; ++ u8 s2; ++ u8 mixed; ++ enum cxd2880_dvbt2_mode fft_mode; ++ u8 l1_rep; ++ enum cxd2880_dvbt2_guard gi; ++ enum cxd2880_dvbt2_papr papr; ++ enum cxd2880_dvbt2_l1post_constell mod; ++ enum cxd2880_dvbt2_l1post_cr cr; ++ enum cxd2880_dvbt2_l1post_fec_type fec; ++ u32 l1_post_size; ++ u32 l1_post_info_size; ++ enum cxd2880_dvbt2_pp pp; ++ u8 tx_id_availability; ++ u16 cell_id; ++ u16 network_id; ++ u16 sys_id; ++ u8 num_frames; ++ u16 num_symbols; ++ u8 regen; ++ u8 post_ext; ++ u8 num_rf_freqs; ++ u8 rf_idx; ++ enum cxd2880_dvbt2_version t2_version; ++ u8 l1_post_scrambled; ++ u8 t2_base_lite; ++ u32 crc32; ++}; ++ ++struct cxd2880_dvbt2_plp { ++ u8 id; ++ enum cxd2880_dvbt2_plp_type type; ++ enum cxd2880_dvbt2_plp_payload payload; ++ u8 ff; ++ u8 first_rf_idx; ++ u8 first_frm_idx; ++ u8 group_id; ++ enum cxd2880_dvbt2_plp_constell constell; ++ enum cxd2880_dvbt2_plp_code_rate plp_cr; ++ u8 rot; ++ enum cxd2880_dvbt2_plp_fec fec; ++ u16 num_blocks_max; ++ u8 frm_int; ++ u8 til_len; ++ u8 til_type; ++ u8 in_band_a_flag; ++ u8 in_band_b_flag; ++ u16 rsvd; ++ enum cxd2880_dvbt2_plp_mode plp_mode; ++ u8 static_flag; ++ u8 static_padding_flag; ++}; ++ ++struct cxd2880_dvbt2_l1post { ++ u16 sub_slices_per_frame; ++ u8 num_plps; ++ u8 num_aux; ++ u8 aux_cfg_rfu; ++ u8 rf_idx; ++ u32 freq; ++ u8 fef_type; ++ u32 fef_length; ++ u8 fef_intvl; ++}; ++ ++struct cxd2880_dvbt2_ofdm { ++ u8 mixed; ++ u8 is_miso; ++ enum cxd2880_dvbt2_mode mode; ++ enum cxd2880_dvbt2_guard gi; ++ enum cxd2880_dvbt2_pp pp; ++ u8 bw_ext; ++ enum cxd2880_dvbt2_papr papr; ++ u16 num_symbols; ++}; ++ ++struct cxd2880_dvbt2_bbheader { ++ enum cxd2880_dvbt2_stream stream_input; ++ u8 is_single_input_stream; ++ u8 is_constant_coding_modulation; ++ u8 issy_indicator; ++ u8 null_packet_deletion; ++ u8 ext; ++ u8 input_stream_identifier; ++ u16 user_packet_length; ++ u16 data_field_length; ++ u8 sync_byte; ++ u32 issy; ++ enum cxd2880_dvbt2_plp_mode plp_mode; ++}; ++ ++#endif +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_integ.c b/drivers/media/dvb-frontends/cxd2880/cxd2880_integ.c +new file mode 100644 +index 0000000000000000000000000000000000000000..5ad6685e2a1d457c5a9b8d31a1d6f4aed526dd04 +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_integ.c +@@ -0,0 +1,99 @@ ++/* ++ * cxd2880_integ.c ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * integration layer common functions ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#include "cxd2880_tnrdmd.h" ++#include "cxd2880_tnrdmd_mon.h" ++#include "cxd2880_integ.h" ++ ++enum cxd2880_ret cxd2880_integ_init(struct cxd2880_tnrdmd *tnr_dmd) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ struct cxd2880_stopwatch timer; ++ u32 elapsed_time = 0; ++ u8 cpu_task_completed = 0; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ ret = cxd2880_tnrdmd_init1(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ ret = cxd2880_stopwatch_start(&timer); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ while (1) { ++ ret = cxd2880_stopwatch_elapsed(&timer, &elapsed_time); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ ret = ++ cxd2880_tnrdmd_check_internal_cpu_status(tnr_dmd, ++ &cpu_task_completed); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (cpu_task_completed) ++ break; ++ ++ if (elapsed_time > CXD2880_TNRDMD_WAIT_INIT_TIMEOUT) ++ return CXD2880_RESULT_ERROR_TIMEOUT; ++ ret = ++ cxd2880_stopwatch_sleep(&timer, ++ CXD2880_TNRDMD_WAIT_INIT_INTVL); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ ret = cxd2880_tnrdmd_init2(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_integ_cancel(struct cxd2880_tnrdmd *tnr_dmd) ++{ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ cxd2880_atomic_set(&tnr_dmd->cancel, 1); ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_integ_check_cancellation(struct cxd2880_tnrdmd ++ *tnr_dmd) ++{ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (cxd2880_atomic_read(&tnr_dmd->cancel) != 0) ++ return CXD2880_RESULT_ERROR_CANCEL; ++ ++ return CXD2880_RESULT_OK; ++} +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_integ.h b/drivers/media/dvb-frontends/cxd2880/cxd2880_integ.h +new file mode 100644 +index 0000000000000000000000000000000000000000..9cfc52dbf9d4fc128506ee355461cd6ca9f9ab53 +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_integ.h +@@ -0,0 +1,44 @@ ++/* ++ * cxd2880_integ.h ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * integration layer common interface ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#ifndef CXD2880_INTEG_H ++#define CXD2880_INTEG_H ++ ++#include "cxd2880_tnrdmd.h" ++ ++#define CXD2880_TNRDMD_WAIT_INIT_TIMEOUT 500 ++#define CXD2880_TNRDMD_WAIT_INIT_INTVL 10 ++ ++#define CXD2880_TNRDMD_WAIT_AGC_STABLE 100 ++ ++enum cxd2880_ret cxd2880_integ_init(struct cxd2880_tnrdmd *tnr_dmd); ++ ++enum cxd2880_ret cxd2880_integ_cancel(struct cxd2880_tnrdmd *tnr_dmd); ++ ++enum cxd2880_ret cxd2880_integ_check_cancellation(struct cxd2880_tnrdmd ++ *tnr_dmd); ++ ++#endif +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_integ_dvbt.c b/drivers/media/dvb-frontends/cxd2880/cxd2880_integ_dvbt.c +new file mode 100644 +index 0000000000000000000000000000000000000000..43b7da69fc6d689c2246047d06473074f48f69e8 +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_integ_dvbt.c +@@ -0,0 +1,197 @@ ++/* ++ * cxd2880_integ_dvbt.c ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * integration layer functions for DVB-T ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#include "cxd2880_tnrdmd_dvbt.h" ++#include "cxd2880_integ_dvbt.h" ++ ++static enum cxd2880_ret dvbt_wait_demod_lock(struct cxd2880_tnrdmd *tnr_dmd); ++ ++enum cxd2880_ret cxd2880_integ_dvbt_tune(struct cxd2880_tnrdmd *tnr_dmd, ++ struct cxd2880_dvbt_tune_param ++ *tune_param) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!tune_param)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) && ++ (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ cxd2880_atomic_set(&tnr_dmd->cancel, 0); ++ ++ if ((tune_param->bandwidth != CXD2880_DTV_BW_5_MHZ) && ++ (tune_param->bandwidth != CXD2880_DTV_BW_6_MHZ) && ++ (tune_param->bandwidth != CXD2880_DTV_BW_7_MHZ) && ++ (tune_param->bandwidth != CXD2880_DTV_BW_8_MHZ)) { ++ return CXD2880_RESULT_ERROR_NOSUPPORT; ++ } ++ ++ ret = cxd2880_tnrdmd_dvbt_tune1(tnr_dmd, tune_param); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ CXD2880_SLEEP(CXD2880_TNRDMD_WAIT_AGC_STABLE); ++ ++ ret = cxd2880_tnrdmd_dvbt_tune2(tnr_dmd, tune_param); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ ret = dvbt_wait_demod_lock(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_integ_dvbt_wait_ts_lock(struct cxd2880_tnrdmd *tnr_dmd) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ enum cxd2880_tnrdmd_lock_result lock = ++ CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT; ++ struct cxd2880_stopwatch timer; ++ u8 continue_wait = 1; ++ u32 elapsed = 0; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = cxd2880_stopwatch_start(&timer); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ for (;;) { ++ ret = cxd2880_stopwatch_elapsed(&timer, &elapsed); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (elapsed >= CXD2880_DVBT_WAIT_TS_LOCK) ++ continue_wait = 0; ++ ++ ret = cxd2880_tnrdmd_dvbt_check_ts_lock(tnr_dmd, &lock); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ switch (lock) { ++ case CXD2880_TNRDMD_LOCK_RESULT_LOCKED: ++ return CXD2880_RESULT_OK; ++ ++ case CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED: ++ return CXD2880_RESULT_ERROR_UNLOCK; ++ ++ default: ++ break; ++ } ++ ++ ret = cxd2880_integ_check_cancellation(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (continue_wait) { ++ ret = ++ cxd2880_stopwatch_sleep(&timer, ++ CXD2880_DVBT_WAIT_LOCK_INTVL); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } else { ++ ret = CXD2880_RESULT_ERROR_TIMEOUT; ++ break; ++ } ++ } ++ ++ return ret; ++} ++ ++static enum cxd2880_ret dvbt_wait_demod_lock(struct cxd2880_tnrdmd *tnr_dmd) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ enum cxd2880_tnrdmd_lock_result lock = ++ CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT; ++ struct cxd2880_stopwatch timer; ++ u8 continue_wait = 1; ++ u32 elapsed = 0; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = cxd2880_stopwatch_start(&timer); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ for (;;) { ++ ret = cxd2880_stopwatch_elapsed(&timer, &elapsed); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (elapsed >= CXD2880_DVBT_WAIT_DMD_LOCK) ++ continue_wait = 0; ++ ++ ret = cxd2880_tnrdmd_dvbt_check_demod_lock(tnr_dmd, &lock); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ switch (lock) { ++ case CXD2880_TNRDMD_LOCK_RESULT_LOCKED: ++ return CXD2880_RESULT_OK; ++ ++ case CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED: ++ return CXD2880_RESULT_ERROR_UNLOCK; ++ ++ default: ++ break; ++ } ++ ++ ret = cxd2880_integ_check_cancellation(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (continue_wait) { ++ ret = ++ cxd2880_stopwatch_sleep(&timer, ++ CXD2880_DVBT_WAIT_LOCK_INTVL); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } else { ++ ret = CXD2880_RESULT_ERROR_TIMEOUT; ++ break; ++ } ++ } ++ ++ return ret; ++} +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_integ_dvbt.h b/drivers/media/dvb-frontends/cxd2880/cxd2880_integ_dvbt.h +new file mode 100644 +index 0000000000000000000000000000000000000000..41f35c07a15e5052d3c09a21f1cc5c2085158690 +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_integ_dvbt.h +@@ -0,0 +1,58 @@ ++/* ++ * cxd2880_integ_dvbt.h ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * integration layer interface for DVB-T ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#ifndef CXD2880_INTEG_DVBT_H ++#define CXD2880_INTEG_DVBT_H ++ ++#include "cxd2880_tnrdmd.h" ++#include "cxd2880_tnrdmd_dvbt.h" ++#include "cxd2880_integ.h" ++ ++#define CXD2880_DVBT_WAIT_DMD_LOCK 1000 ++#define CXD2880_DVBT_WAIT_TS_LOCK 1000 ++#define CXD2880_DVBT_WAIT_LOCK_INTVL 10 ++ ++struct cxd2880_integ_dvbt_scan_param { ++ u32 start_frequency_khz; ++ u32 end_frequency_khz; ++ u32 step_frequency_khz; ++ enum cxd2880_dtv_bandwidth bandwidth; ++}; ++ ++struct cxd2880_integ_dvbt_scan_result { ++ u32 center_freq_khz; ++ enum cxd2880_ret tune_result; ++ struct cxd2880_dvbt_tune_param dvbt_tune_param; ++}; ++ ++enum cxd2880_ret cxd2880_integ_dvbt_tune(struct cxd2880_tnrdmd *tnr_dmd, ++ struct cxd2880_dvbt_tune_param ++ *tune_param); ++ ++enum cxd2880_ret cxd2880_integ_dvbt_wait_ts_lock(struct cxd2880_tnrdmd ++ *tnr_dmd); ++ ++#endif +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_integ_dvbt2.c b/drivers/media/dvb-frontends/cxd2880/cxd2880_integ_dvbt2.c +new file mode 100644 +index 0000000000000000000000000000000000000000..1d60b9c236d844df239e3adfa0da40192555c7ee +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_integ_dvbt2.c +@@ -0,0 +1,311 @@ ++/* ++ * cxd2880_integ_dvbt2.c ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * integration layer functions for DVB-T2 ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#include "cxd2880_tnrdmd_dvbt2.h" ++#include "cxd2880_tnrdmd_dvbt2_mon.h" ++#include "cxd2880_integ_dvbt2.h" ++ ++static enum cxd2880_ret dvbt2_wait_demod_lock(struct cxd2880_tnrdmd *tnr_dmd, ++ enum cxd2880_dvbt2_profile ++ profile); ++ ++static enum cxd2880_ret dvbt2_wait_l1_post_lock(struct cxd2880_tnrdmd *tnr_dmd); ++ ++enum cxd2880_ret cxd2880_integ_dvbt2_tune(struct cxd2880_tnrdmd *tnr_dmd, ++ struct cxd2880_dvbt2_tune_param ++ *tune_param) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!tune_param)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) && ++ (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ cxd2880_atomic_set(&tnr_dmd->cancel, 0); ++ ++ if ((tune_param->bandwidth != CXD2880_DTV_BW_1_7_MHZ) && ++ (tune_param->bandwidth != CXD2880_DTV_BW_5_MHZ) && ++ (tune_param->bandwidth != CXD2880_DTV_BW_6_MHZ) && ++ (tune_param->bandwidth != CXD2880_DTV_BW_7_MHZ) && ++ (tune_param->bandwidth != CXD2880_DTV_BW_8_MHZ)) { ++ return CXD2880_RESULT_ERROR_NOSUPPORT; ++ } ++ ++ if ((tune_param->profile != CXD2880_DVBT2_PROFILE_BASE) && ++ (tune_param->profile != CXD2880_DVBT2_PROFILE_LITE)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ ret = cxd2880_tnrdmd_dvbt2_tune1(tnr_dmd, tune_param); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ CXD2880_SLEEP(CXD2880_TNRDMD_WAIT_AGC_STABLE); ++ ++ ret = cxd2880_tnrdmd_dvbt2_tune2(tnr_dmd, tune_param); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ ret = dvbt2_wait_demod_lock(tnr_dmd, tune_param->profile); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ ret = cxd2880_tnrdmd_dvbt2_diver_fef_setting(tnr_dmd); ++ if (ret == CXD2880_RESULT_ERROR_HW_STATE) ++ return CXD2880_RESULT_ERROR_UNLOCK; ++ else if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ ret = dvbt2_wait_l1_post_lock(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ { ++ u8 plp_not_found; ++ ++ ret = ++ cxd2880_tnrdmd_dvbt2_mon_data_plp_error(tnr_dmd, ++ &plp_not_found); ++ if (ret == CXD2880_RESULT_ERROR_HW_STATE) ++ return CXD2880_RESULT_ERROR_UNLOCK; ++ else if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (plp_not_found) { ++ ret = CXD2880_RESULT_OK_CONFIRM; ++ tune_param->tune_info = ++ CXD2880_TNRDMD_DVBT2_TUNE_INFO_INVALID_PLP_ID; ++ } else { ++ tune_param->tune_info = ++ CXD2880_TNRDMD_DVBT2_TUNE_INFO_OK; ++ } ++ } ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_integ_dvbt2_wait_ts_lock(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum cxd2880_dvbt2_profile ++ profile) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ enum cxd2880_tnrdmd_lock_result lock = ++ CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT; ++ u16 timeout = 0; ++ struct cxd2880_stopwatch timer; ++ u8 continue_wait = 1; ++ u32 elapsed = 0; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = cxd2880_stopwatch_start(&timer); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (profile == CXD2880_DVBT2_PROFILE_BASE) ++ timeout = CXD2880_DVBT2_BASE_WAIT_TS_LOCK; ++ else if (profile == CXD2880_DVBT2_PROFILE_LITE) ++ timeout = CXD2880_DVBT2_LITE_WAIT_TS_LOCK; ++ else ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ for (;;) { ++ ret = cxd2880_stopwatch_elapsed(&timer, &elapsed); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (elapsed >= timeout) ++ continue_wait = 0; ++ ++ ret = cxd2880_tnrdmd_dvbt2_check_ts_lock(tnr_dmd, &lock); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ switch (lock) { ++ case CXD2880_TNRDMD_LOCK_RESULT_LOCKED: ++ return CXD2880_RESULT_OK; ++ ++ case CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED: ++ return CXD2880_RESULT_ERROR_UNLOCK; ++ ++ default: ++ break; ++ } ++ ++ ret = cxd2880_integ_check_cancellation(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (continue_wait) { ++ ret = ++ cxd2880_stopwatch_sleep(&timer, ++ CXD2880_DVBT2_WAIT_LOCK_INTVL); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } else { ++ ret = CXD2880_RESULT_ERROR_TIMEOUT; ++ break; ++ } ++ } ++ ++ return ret; ++} ++ ++static enum cxd2880_ret dvbt2_wait_demod_lock(struct cxd2880_tnrdmd *tnr_dmd, ++ enum cxd2880_dvbt2_profile ++ profile) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ enum cxd2880_tnrdmd_lock_result lock = ++ CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT; ++ u16 timeout = 0; ++ struct cxd2880_stopwatch timer; ++ u8 continue_wait = 1; ++ u32 elapsed = 0; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = cxd2880_stopwatch_start(&timer); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (profile == CXD2880_DVBT2_PROFILE_BASE) ++ timeout = CXD2880_DVBT2_BASE_WAIT_DMD_LOCK; ++ else if ((profile == CXD2880_DVBT2_PROFILE_LITE) || ++ (profile == CXD2880_DVBT2_PROFILE_ANY)) ++ timeout = CXD2880_DVBT2_LITE_WAIT_DMD_LOCK; ++ else ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ for (;;) { ++ ret = cxd2880_stopwatch_elapsed(&timer, &elapsed); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (elapsed >= timeout) ++ continue_wait = 0; ++ ++ ret = cxd2880_tnrdmd_dvbt2_check_demod_lock(tnr_dmd, &lock); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ switch (lock) { ++ case CXD2880_TNRDMD_LOCK_RESULT_LOCKED: ++ return CXD2880_RESULT_OK; ++ ++ case CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED: ++ return CXD2880_RESULT_ERROR_UNLOCK; ++ ++ default: ++ break; ++ } ++ ++ ret = cxd2880_integ_check_cancellation(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (continue_wait) { ++ ret = ++ cxd2880_stopwatch_sleep(&timer, ++ CXD2880_DVBT2_WAIT_LOCK_INTVL); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } else { ++ ret = CXD2880_RESULT_ERROR_TIMEOUT; ++ break; ++ } ++ } ++ ++ return ret; ++} ++ ++static enum cxd2880_ret dvbt2_wait_l1_post_lock(struct cxd2880_tnrdmd *tnr_dmd) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ struct cxd2880_stopwatch timer; ++ u8 continue_wait = 1; ++ u32 elapsed = 0; ++ u8 l1_post_valid; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ ret = cxd2880_stopwatch_start(&timer); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ for (;;) { ++ ret = cxd2880_stopwatch_elapsed(&timer, &elapsed); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (elapsed >= CXD2880_DVBT2_L1POST_TIMEOUT) ++ continue_wait = 0; ++ ++ ret = ++ cxd2880_tnrdmd_dvbt2_check_l1post_valid(tnr_dmd, ++ &l1_post_valid); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (l1_post_valid) ++ return CXD2880_RESULT_OK; ++ ++ ret = cxd2880_integ_check_cancellation(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (continue_wait) { ++ ret = ++ cxd2880_stopwatch_sleep(&timer, ++ CXD2880_DVBT2_WAIT_LOCK_INTVL); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } else { ++ ret = CXD2880_RESULT_ERROR_TIMEOUT; ++ break; ++ } ++ } ++ ++ return ret; ++} +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_integ_dvbt2.h b/drivers/media/dvb-frontends/cxd2880/cxd2880_integ_dvbt2.h +new file mode 100644 +index 0000000000000000000000000000000000000000..bc72eb8188f2e5304cef7db687291b56eb728f8d +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_integ_dvbt2.h +@@ -0,0 +1,64 @@ ++/* ++ * cxd2880_integ_dvbt2.h ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * integration layer interface for DVB-T2 ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#ifndef CXD2880_INTEG_DVBT2_H ++#define CXD2880_INTEG_DVBT2_H ++ ++#include "cxd2880_tnrdmd.h" ++#include "cxd2880_tnrdmd_dvbt2.h" ++#include "cxd2880_integ.h" ++ ++#define CXD2880_DVBT2_BASE_WAIT_DMD_LOCK 3500 ++#define CXD2880_DVBT2_BASE_WAIT_TS_LOCK 1500 ++#define CXD2880_DVBT2_LITE_WAIT_DMD_LOCK 5000 ++#define CXD2880_DVBT2_LITE_WAIT_TS_LOCK 2300 ++#define CXD2880_DVBT2_WAIT_LOCK_INTVL 10 ++#define CXD2880_DVBT2_L1POST_TIMEOUT 500 ++ ++struct cxd2880_integ_dvbt2_scan_param { ++ u32 start_frequency_khz; ++ u32 end_frequency_khz; ++ u32 step_frequency_khz; ++ enum cxd2880_dtv_bandwidth bandwidth; ++ enum cxd2880_dvbt2_profile t2_profile; ++}; ++ ++struct cxd2880_integ_dvbt2_scan_result { ++ u32 center_freq_khz; ++ enum cxd2880_ret tune_result; ++ struct cxd2880_dvbt2_tune_param dvbt2_tune_param; ++}; ++ ++enum cxd2880_ret cxd2880_integ_dvbt2_tune(struct cxd2880_tnrdmd *tnr_dmd, ++ struct cxd2880_dvbt2_tune_param ++ *tune_param); ++ ++enum cxd2880_ret cxd2880_integ_dvbt2_wait_ts_lock(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum cxd2880_dvbt2_profile ++ profile); ++ ++#endif +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_io.c b/drivers/media/dvb-frontends/cxd2880/cxd2880_io.c +new file mode 100644 +index 0000000000000000000000000000000000000000..f0f82055a953337a3fed96feedc2ca5b8d961c4f +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_io.c +@@ -0,0 +1,68 @@ ++/* ++ * cxd2880_io.c ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * register I/O interface functions ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#include "cxd2880_io.h" ++ ++enum cxd2880_ret cxd2880_io_common_write_one_reg(struct cxd2880_io *io, ++ enum cxd2880_io_tgt tgt, ++ u8 sub_address, u8 data) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if (!io) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ ret = io->write_regs(io, tgt, sub_address, &data, 1); ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_io_set_reg_bits(struct cxd2880_io *io, ++ enum cxd2880_io_tgt tgt, ++ u8 sub_address, u8 data, u8 mask) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if (!io) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (mask == 0x00) ++ return CXD2880_RESULT_OK; ++ ++ if (mask != 0xFF) { ++ u8 rdata = 0x00; ++ ++ ret = io->read_regs(io, tgt, sub_address, &rdata, 1); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ data = (u8)((data & mask) | (rdata & (mask ^ 0xFF))); ++ } ++ ++ ret = io->write_reg(io, tgt, sub_address, data); ++ ++ return ret; ++} +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_io.h b/drivers/media/dvb-frontends/cxd2880/cxd2880_io.h +new file mode 100644 +index 0000000000000000000000000000000000000000..4d6db13cf9109373eb1262218b853ef37283958b +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_io.h +@@ -0,0 +1,62 @@ ++/* ++ * cxd2880_io.h ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * register I/O interface definitions ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#ifndef CXD2880_IO_H ++#define CXD2880_IO_H ++ ++#include "cxd2880_common.h" ++ ++enum cxd2880_io_tgt { ++ CXD2880_IO_TGT_SYS, ++ CXD2880_IO_TGT_DMD ++}; ++ ++struct cxd2880_io { ++ enum cxd2880_ret (*read_regs)(struct cxd2880_io *io, ++ enum cxd2880_io_tgt tgt, u8 sub_address, ++ u8 *data, u32 size); ++ enum cxd2880_ret (*write_regs)(struct cxd2880_io *io, ++ enum cxd2880_io_tgt tgt, u8 sub_address, ++ const u8 *data, u32 size); ++ enum cxd2880_ret (*write_reg)(struct cxd2880_io *io, ++ enum cxd2880_io_tgt tgt, u8 sub_address, ++ u8 data); ++ void *if_object; ++ u8 i2c_address_sys; ++ u8 i2c_address_demod; ++ u8 slave_select; ++ void *user; ++}; ++ ++enum cxd2880_ret cxd2880_io_common_write_one_reg(struct cxd2880_io *io, ++ enum cxd2880_io_tgt tgt, ++ u8 sub_address, u8 data); ++ ++enum cxd2880_ret cxd2880_io_set_reg_bits(struct cxd2880_io *io, ++ enum cxd2880_io_tgt tgt, ++ u8 sub_address, u8 data, u8 mask); ++ ++#endif +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_math.c b/drivers/media/dvb-frontends/cxd2880/cxd2880_math.c +new file mode 100644 +index 0000000000000000000000000000000000000000..434c827898ff5f4a44bcc013fa7df43c168cafc4 +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_math.c +@@ -0,0 +1,89 @@ ++/* ++ * cxd2880_math.c ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * mathmatics functions ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#include "cxd2880_math.h" ++ ++#define MAX_BIT_PRECISION 5 ++#define FRAC_BITMASK 0x1F ++#define LOG2_10_100X 332 ++#define LOG2_E_100X 144 ++ ++static const u8 log2_look_up[] = { ++ 0, 4, ++ 9, 13, ++ 17, 21, ++ 25, 29, ++ 32, 36, ++ 39, 43, ++ 46, 49, ++ 52, 55, ++ 58, 61, ++ 64, 67, ++ 70, 73, ++ 75, 78, ++ 81, 83, ++ 86, 88, ++ 91, 93, ++ 95, 98 ++}; ++ ++u32 cxd2880_math_log2(u32 x) ++{ ++ u8 count = 0; ++ u8 index = 0; ++ u32 xval = x; ++ ++ for (x >>= 1; x > 0; x >>= 1) ++ count++; ++ ++ x = count * 100; ++ ++ if (count > 0) { ++ if (count <= MAX_BIT_PRECISION) { ++ index = ++ (u8)(xval << (MAX_BIT_PRECISION - count)) & ++ FRAC_BITMASK; ++ x += log2_look_up[index]; ++ } else { ++ index = ++ (u8)(xval >> (count - MAX_BIT_PRECISION)) & ++ FRAC_BITMASK; ++ x += log2_look_up[index]; ++ } ++ } ++ ++ return x; ++} ++ ++u32 cxd2880_math_log10(u32 x) ++{ ++ return ((100 * cxd2880_math_log2(x) + LOG2_10_100X / 2) / LOG2_10_100X); ++} ++ ++u32 cxd2880_math_log(u32 x) ++{ ++ return ((100 * cxd2880_math_log2(x) + LOG2_E_100X / 2) / LOG2_E_100X); ++} +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_math.h b/drivers/media/dvb-frontends/cxd2880/cxd2880_math.h +new file mode 100644 +index 0000000000000000000000000000000000000000..94211835a4adca74e4ddad3ea417f01d9f8eedef +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_math.h +@@ -0,0 +1,40 @@ ++/* ++ * cxd2880_math.h ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * mathmatics definitions ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#ifndef CXD2880_MATH_H_ ++#define CXD2880_MATH_H_ ++ ++#include "cxd2880_common.h" ++ ++u32 cxd2880_math_log2(u32 x); ++u32 cxd2880_math_log10(u32 x); ++u32 cxd2880_math_log(u32 x); ++ ++#ifndef min ++#define min(a, b) (((a) < (b)) ? (a) : (b)) ++#endif ++ ++#endif +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_spi.h b/drivers/media/dvb-frontends/cxd2880/cxd2880_spi.h +new file mode 100644 +index 0000000000000000000000000000000000000000..81e5be7479623e536f6b472a38ae8af785291506 +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_spi.h +@@ -0,0 +1,51 @@ ++/* ++ * cxd2880_spi.h ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * SPI access definitions ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#ifndef CXD2880_SPI_H ++#define CXD2880_SPI_H ++ ++#include "cxd2880_common.h" ++ ++enum cxd2880_spi_mode { ++ CXD2880_SPI_MODE_0, ++ CXD2880_SPI_MODE_1, ++ CXD2880_SPI_MODE_2, ++ CXD2880_SPI_MODE_3 ++}; ++ ++struct cxd2880_spi { ++ enum cxd2880_ret (*read)(struct cxd2880_spi *spi, u8 *data, ++ u32 size); ++ enum cxd2880_ret (*write)(struct cxd2880_spi *spi, const u8 *data, ++ u32 size); ++ enum cxd2880_ret (*write_read)(struct cxd2880_spi *spi, ++ const u8 *tx_data, u32 tx_size, ++ u8 *rx_data, u32 rx_size); ++ u32 flags; ++ void *user; ++}; ++ ++#endif +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_spi_device.c b/drivers/media/dvb-frontends/cxd2880/cxd2880_spi_device.c +new file mode 100644 +index 0000000000000000000000000000000000000000..af9ed40c900b09c0566748d56991573965233ab4 +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_spi_device.c +@@ -0,0 +1,130 @@ ++/* ++ * cxd2880_spi_device.c ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * SPI access functions ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#include ++ ++#include "cxd2880_spi_device.h" ++ ++static enum cxd2880_ret cxd2880_spi_device_write(struct cxd2880_spi *spi, ++ const u8 *data, u32 size) ++{ ++ struct cxd2880_spi_device *spi_device = NULL; ++ struct spi_message msg; ++ struct spi_transfer tx; ++ int result = 0; ++ ++ if ((!spi) || (!spi->user) || (!data) || (size == 0)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ spi_device = (struct cxd2880_spi_device *)(spi->user); ++ ++ memset(&tx, 0, sizeof(tx)); ++ tx.tx_buf = data; ++ tx.len = size; ++ ++ spi_message_init(&msg); ++ spi_message_add_tail(&tx, &msg); ++ result = spi_sync(spi_device->spi, &msg); ++ ++ if (result < 0) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++static enum cxd2880_ret cxd2880_spi_device_write_read(struct cxd2880_spi *spi, ++ const u8 *tx_data, ++ u32 tx_size, ++ u8 *rx_data, ++ u32 rx_size) ++{ ++ struct cxd2880_spi_device *spi_device = NULL; ++ int result = 0; ++ ++ if ((!spi) || (!spi->user) || (!tx_data) || ++ (tx_size == 0) || (!rx_data) || (rx_size == 0)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ spi_device = (struct cxd2880_spi_device *)(spi->user); ++ ++ result = spi_write_then_read(spi_device->spi, tx_data, ++ tx_size, rx_data, rx_size); ++ if (result < 0) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret ++cxd2880_spi_device_initialize(struct cxd2880_spi_device *spi_device, ++ enum cxd2880_spi_mode mode, ++ u32 speed_hz) ++{ ++ int result = 0; ++ struct spi_device *spi = spi_device->spi; ++ ++ switch (mode) { ++ case CXD2880_SPI_MODE_0: ++ spi->mode = SPI_MODE_0; ++ break; ++ case CXD2880_SPI_MODE_1: ++ spi->mode = SPI_MODE_1; ++ break; ++ case CXD2880_SPI_MODE_2: ++ spi->mode = SPI_MODE_2; ++ break; ++ case CXD2880_SPI_MODE_3: ++ spi->mode = SPI_MODE_3; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_ARG; ++ } ++ ++ spi->max_speed_hz = speed_hz; ++ spi->bits_per_word = 8; ++ result = spi_setup(spi); ++ if (result != 0) { ++ pr_err("spi_setup failed %d\n", result); ++ return CXD2880_RESULT_ERROR_ARG; ++ } ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_spi_device_create_spi(struct cxd2880_spi *spi, ++ struct cxd2880_spi_device *spi_device) ++{ ++ if ((!spi) || (!spi_device)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ spi->read = NULL; ++ spi->write = cxd2880_spi_device_write; ++ spi->write_read = cxd2880_spi_device_write_read; ++ spi->flags = 0; ++ spi->user = spi_device; ++ ++ return CXD2880_RESULT_OK; ++} +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_spi_device.h b/drivers/media/dvb-frontends/cxd2880/cxd2880_spi_device.h +new file mode 100644 +index 0000000000000000000000000000000000000000..343d9161d537b2eb5bcc61e5cbd4c9fa04f5f8fe +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_spi_device.h +@@ -0,0 +1,45 @@ ++/* ++ * cxd2880_spi_device.h ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * SPI access interface ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#ifndef CXD2880_SPI_DEVICE_H ++#define CXD2880_SPI_DEVICE_H ++ ++#include "cxd2880_spi.h" ++ ++struct cxd2880_spi_device { ++ struct spi_device *spi; ++}; ++ ++enum cxd2880_ret ++cxd2880_spi_device_initialize(struct cxd2880_spi_device *spi_device, ++ enum cxd2880_spi_mode mode, ++ u32 speedHz); ++ ++enum cxd2880_ret ++cxd2880_spi_device_create_spi(struct cxd2880_spi *spi, ++ struct cxd2880_spi_device *spi_device); ++ ++#endif /* CXD2880_SPI_DEVICE_H */ +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_stdlib.h b/drivers/media/dvb-frontends/cxd2880/cxd2880_stdlib.h +new file mode 100644 +index 0000000000000000000000000000000000000000..b9ca1b9df1101b3a1cd78db593c9f36b08f67e01 +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_stdlib.h +@@ -0,0 +1,35 @@ ++/* ++ * cxd2880_stdlib.h ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * standard lib function aliases ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#ifndef CXD2880_STDLIB_H ++#define CXD2880_STDLIB_H ++ ++#include ++ ++#define cxd2880_memcpy memcpy ++#define cxd2880_memset memset ++ ++#endif +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_stopwatch_port.c b/drivers/media/dvb-frontends/cxd2880/cxd2880_stopwatch_port.c +new file mode 100644 +index 0000000000000000000000000000000000000000..14ad6aa6c4c0500c0e0ed59ab1c28f1dfe13f1d3 +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_stopwatch_port.c +@@ -0,0 +1,71 @@ ++/* ++ * cxd2880_stopwatch_port.c ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * time measurement functions ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#include "cxd2880_common.h" ++ ++#include ++#include ++#include ++ ++static u32 get_time_count(void) ++{ ++ struct timespec tp; ++ ++ getnstimeofday(&tp); ++ ++ return (u32)((tp.tv_sec * 1000) + (tp.tv_nsec / 1000000)); ++} ++ ++enum cxd2880_ret cxd2880_stopwatch_start(struct cxd2880_stopwatch *stopwatch) ++{ ++ if (!stopwatch) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ stopwatch->start_time = get_time_count(); ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_stopwatch_sleep(struct cxd2880_stopwatch *stopwatch, ++ u32 ms) ++{ ++ if (!stopwatch) ++ return CXD2880_RESULT_ERROR_ARG; ++ CXD2880_ARG_UNUSED(*stopwatch); ++ CXD2880_SLEEP(ms); ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_stopwatch_elapsed(struct cxd2880_stopwatch *stopwatch, ++ u32 *elapsed) ++{ ++ if (!stopwatch || !elapsed) ++ return CXD2880_RESULT_ERROR_ARG; ++ *elapsed = get_time_count() - stopwatch->start_time; ++ ++ return CXD2880_RESULT_OK; ++} +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd.c b/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd.c +new file mode 100644 +index 0000000000000000000000000000000000000000..286384ae012443c432a232401ff35157c57ed0f5 +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd.c +@@ -0,0 +1,3925 @@ ++/* ++ * cxd2880_tnrdmd.c ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * common control functions ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#include "cxd2880_common.h" ++#include "cxd2880_stdlib.h" ++#include "cxd2880_tnrdmd.h" ++#include "cxd2880_tnrdmd_mon.h" ++#include "cxd2880_tnrdmd_dvbt.h" ++#include "cxd2880_tnrdmd_dvbt2.h" ++ ++static enum cxd2880_ret p_init1(struct cxd2880_tnrdmd *tnr_dmd) ++{ ++ u8 data = 0; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if ((tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE) || ++ (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN)) { ++ switch (tnr_dmd->create_param.ts_output_if) { ++ case CXD2880_TNRDMD_TSOUT_IF_TS: ++ data = 0x00; ++ break; ++ case CXD2880_TNRDMD_TSOUT_IF_SPI: ++ data = 0x01; ++ break; ++ case CXD2880_TNRDMD_TSOUT_IF_SDIO: ++ data = 0x02; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_ARG; ++ } ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x10, ++ data) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x11, ++ 0x16) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x10) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ switch (tnr_dmd->chip_id) { ++ case CXD2880_TNRDMD_CHIP_ID_CXD2880_ES1_0X: ++ data = 0x1A; ++ break; ++ case CXD2880_TNRDMD_CHIP_ID_CXD2880_ES1_11: ++ data = 0x16; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_NOSUPPORT; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x10, ++ data) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->create_param.en_internal_ldo) ++ data = 0x01; ++ else ++ data = 0x00; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x11, ++ data) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x13, ++ data) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x12, ++ data) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x10) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ switch (tnr_dmd->chip_id) { ++ case CXD2880_TNRDMD_CHIP_ID_CXD2880_ES1_0X: ++ data = 0x01; ++ break; ++ case CXD2880_TNRDMD_CHIP_ID_CXD2880_ES1_11: ++ data = 0x00; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_NOSUPPORT; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x69, ++ data) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++static enum cxd2880_ret p_init2(struct cxd2880_tnrdmd *tnr_dmd) ++{ ++ u8 data[6] = { 0 }; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ data[0] = tnr_dmd->create_param.xosc_cap; ++ data[1] = tnr_dmd->create_param.xosc_i; ++ switch (tnr_dmd->create_param.xtal_share_type) { ++ case CXD2880_TNRDMD_XTAL_SHARE_NONE: ++ data[2] = 0x01; ++ data[3] = 0x00; ++ break; ++ case CXD2880_TNRDMD_XTAL_SHARE_EXTREF: ++ data[2] = 0x00; ++ data[3] = 0x00; ++ break; ++ case CXD2880_TNRDMD_XTAL_SHARE_MASTER: ++ data[2] = 0x01; ++ data[3] = 0x01; ++ break; ++ case CXD2880_TNRDMD_XTAL_SHARE_SLAVE: ++ data[2] = 0x00; ++ data[3] = 0x01; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_ARG; ++ } ++ data[4] = 0x06; ++ data[5] = 0x00; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x13, data, ++ 6) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++static enum cxd2880_ret p_init3(struct cxd2880_tnrdmd *tnr_dmd) ++{ ++ u8 data[2] = { 0 }; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ switch (tnr_dmd->diver_mode) { ++ case CXD2880_TNRDMD_DIVERMODE_SINGLE: ++ data[0] = 0x00; ++ break; ++ case CXD2880_TNRDMD_DIVERMODE_MAIN: ++ data[0] = 0x03; ++ break; ++ case CXD2880_TNRDMD_DIVERMODE_SUB: ++ data[0] = 0x02; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_ARG; ++ } ++ ++ data[1] = 0x01; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x1F, data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++static enum cxd2880_ret rf_init1(struct cxd2880_tnrdmd *tnr_dmd) ++{ ++ u8 data[80] = { 0 }; ++ u8 addr = 0; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ data[0] = 0x01; ++ data[1] = 0x00; ++ data[2] = 0x01; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x21, data, ++ 3) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x10) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ data[0] = 0x01; ++ data[1] = 0x01; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x17, data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->create_param.stationary_use) { ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x1A, ++ 0x06) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x4F, ++ 0x18) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x61, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x71, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x9D, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x7D, ++ 0x02) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x8F, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x8B, ++ 0xC6) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x9A, ++ 0x03) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x1C, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ data[0] = 0x00; ++ if ((tnr_dmd->create_param.is_cxd2881gg) && ++ (tnr_dmd->create_param.xtal_share_type == ++ CXD2880_TNRDMD_XTAL_SHARE_SLAVE)) ++ data[1] = 0x00; ++ else ++ data[1] = 0x1F; ++ data[2] = 0x0A; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0xB5, data, ++ 3) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0xB9, ++ 0x07) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x33, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0xC1, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0xC4, ++ 0x1E) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->chip_id == CXD2880_TNRDMD_CHIP_ID_CXD2880_ES1_0X) { ++ data[0] = 0x34; ++ data[1] = 0x2C; ++ } else { ++ data[0] = 0x2F; ++ data[1] = 0x25; ++ } ++ data[2] = 0x15; ++ data[3] = 0x19; ++ data[4] = 0x1B; ++ data[5] = 0x15; ++ data[6] = 0x19; ++ data[7] = 0x1B; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0xD9, data, ++ 8) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x11) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ data[0] = 0x6C; ++ data[1] = 0x10; ++ data[2] = 0xA6; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x44, data, ++ 3) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ data[0] = 0x16; ++ data[1] = 0xA8; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x50, data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ data[0] = 0x00; ++ data[1] = 0x22; ++ data[2] = 0x00; ++ data[3] = 0x88; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x62, data, ++ 4) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x74, ++ 0x75) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ data[0] = 0x05; ++ data[1] = 0x05; ++ data[2] = 0x05; ++ data[3] = 0x05; ++ data[4] = 0x05; ++ data[5] = 0x05; ++ data[6] = 0x05; ++ data[7] = 0x05; ++ data[8] = 0x05; ++ data[9] = 0x04; ++ data[10] = 0x04; ++ data[11] = 0x04; ++ data[12] = 0x03; ++ data[13] = 0x03; ++ data[14] = 0x03; ++ data[15] = 0x04; ++ data[16] = 0x04; ++ data[17] = 0x05; ++ data[18] = 0x05; ++ data[19] = 0x05; ++ data[20] = 0x02; ++ data[21] = 0x02; ++ data[22] = 0x02; ++ data[23] = 0x02; ++ data[24] = 0x02; ++ data[25] = 0x02; ++ data[26] = 0x02; ++ data[27] = 0x02; ++ data[28] = 0x02; ++ data[29] = 0x03; ++ data[30] = 0x02; ++ data[31] = 0x01; ++ data[32] = 0x01; ++ data[33] = 0x01; ++ data[34] = 0x02; ++ data[35] = 0x02; ++ data[36] = 0x03; ++ data[37] = 0x04; ++ data[38] = 0x04; ++ data[39] = 0x04; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x7F, data, ++ 40) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x16) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ data[0] = 0x00; ++ data[1] = 0x71; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x10, data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x23, ++ 0x89) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ data[0] = 0xFF; ++ data[1] = 0x00; ++ data[2] = 0x00; ++ data[3] = 0x00; ++ data[4] = 0x00; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x27, data, ++ 5) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ data[0] = 0x00; ++ data[1] = 0x00; ++ data[2] = 0x00; ++ data[3] = 0x00; ++ data[4] = 0x00; ++ data[5] = 0x01; ++ data[6] = 0x00; ++ data[7] = 0x01; ++ data[8] = 0x00; ++ data[9] = 0x02; ++ data[10] = 0x00; ++ data[11] = 0x63; ++ data[12] = 0x00; ++ data[13] = 0x00; ++ data[14] = 0x00; ++ data[15] = 0x03; ++ data[16] = 0x00; ++ data[17] = 0x04; ++ data[18] = 0x00; ++ data[19] = 0x04; ++ data[20] = 0x00; ++ data[21] = 0x06; ++ data[22] = 0x00; ++ data[23] = 0x06; ++ data[24] = 0x00; ++ data[25] = 0x08; ++ data[26] = 0x00; ++ data[27] = 0x09; ++ data[28] = 0x00; ++ data[29] = 0x0B; ++ data[30] = 0x00; ++ data[31] = 0x0B; ++ data[32] = 0x00; ++ data[33] = 0x0D; ++ data[34] = 0x00; ++ data[35] = 0x0D; ++ data[36] = 0x00; ++ data[37] = 0x0F; ++ data[38] = 0x00; ++ data[39] = 0x0F; ++ data[40] = 0x00; ++ data[41] = 0x0F; ++ data[42] = 0x00; ++ data[43] = 0x10; ++ data[44] = 0x00; ++ data[45] = 0x79; ++ data[46] = 0x00; ++ data[47] = 0x00; ++ data[48] = 0x00; ++ data[49] = 0x02; ++ data[50] = 0x00; ++ data[51] = 0x00; ++ data[52] = 0x00; ++ data[53] = 0x03; ++ data[54] = 0x00; ++ data[55] = 0x01; ++ data[56] = 0x00; ++ data[57] = 0x03; ++ data[58] = 0x00; ++ data[59] = 0x03; ++ data[60] = 0x00; ++ data[61] = 0x03; ++ data[62] = 0x00; ++ data[63] = 0x04; ++ data[64] = 0x00; ++ data[65] = 0x04; ++ data[66] = 0x00; ++ data[67] = 0x06; ++ data[68] = 0x00; ++ data[69] = 0x05; ++ data[70] = 0x00; ++ data[71] = 0x07; ++ data[72] = 0x00; ++ data[73] = 0x07; ++ data[74] = 0x00; ++ data[75] = 0x08; ++ data[76] = 0x00; ++ data[77] = 0x0A; ++ data[78] = 0x03; ++ data[79] = 0xE0; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x3A, data, ++ 80) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ data[0] = 0x03; ++ data[1] = 0xE0; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0xBC, data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x10) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x51, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0xC5, ++ 0x07) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x11) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x70, ++ 0xE9) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x76, ++ 0x0A) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x78, ++ 0x32) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x7A, ++ 0x46) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x7C, ++ 0x86) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x7E, ++ 0xA4) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x10) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0xE1, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->create_param.stationary_use) { ++ data[0] = 0x06; ++ data[1] = 0x07; ++ data[2] = 0x1A; ++ } else { ++ data[0] = 0x00; ++ data[1] = 0x08; ++ data[2] = 0x19; ++ } ++ data[3] = 0x0E; ++ data[4] = 0x09; ++ data[5] = 0x0E; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x12) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ for (addr = 0x10; addr < 0x9F; addr += 6) { ++ if (tnr_dmd->lna_thrs_tbl_air) { ++ u8 idx = 0; ++ ++ idx = (addr - 0x10) / 6; ++ data[0] = ++ tnr_dmd->lna_thrs_tbl_air->thrs[idx].off_on; ++ data[1] = ++ tnr_dmd->lna_thrs_tbl_air->thrs[idx].on_off; ++ } ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, addr, ++ data, ++ 6) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ data[0] = 0x00; ++ data[1] = 0x08; ++ if (tnr_dmd->create_param.stationary_use) ++ data[2] = 0x1A; ++ else ++ data[2] = 0x19; ++ data[3] = 0x0E; ++ data[4] = 0x09; ++ data[5] = 0x0E; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x13) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ for (addr = 0x10; addr < 0xCF; addr += 6) { ++ if (tnr_dmd->lna_thrs_tbl_cable) { ++ u8 idx = 0; ++ ++ idx = (addr - 0x10) / 6; ++ data[0] = ++ tnr_dmd->lna_thrs_tbl_cable->thrs[idx].off_on; ++ data[1] = ++ tnr_dmd->lna_thrs_tbl_cable->thrs[idx].on_off; ++ } ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, addr, ++ data, ++ 6) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x11) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ data[0] = 0x08; ++ data[1] = 0x09; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0xBD, data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ data[0] = 0x08; ++ data[1] = 0x09; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0xC4, data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ data[0] = 0x20; ++ data[1] = 0x20; ++ data[2] = 0x30; ++ data[3] = 0x41; ++ data[4] = 0x50; ++ data[5] = 0x5F; ++ data[6] = 0x6F; ++ data[7] = 0x80; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0xC9, data, ++ 8) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x14) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ data[0] = 0x15; ++ data[1] = 0x18; ++ data[2] = 0x00; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x10, data, ++ 3) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x15, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x16) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ data[0] = 0x00; ++ data[1] = 0x09; ++ data[2] = 0x00; ++ data[3] = 0x08; ++ data[4] = 0x00; ++ data[5] = 0x07; ++ data[6] = 0x00; ++ data[7] = 0x06; ++ data[8] = 0x00; ++ data[9] = 0x05; ++ data[10] = 0x00; ++ data[11] = 0x03; ++ data[12] = 0x00; ++ data[13] = 0x02; ++ data[14] = 0x00; ++ data[15] = 0x00; ++ data[16] = 0x00; ++ data[17] = 0x78; ++ data[18] = 0x00; ++ data[19] = 0x00; ++ data[20] = 0x00; ++ data[21] = 0x06; ++ data[22] = 0x00; ++ data[23] = 0x08; ++ data[24] = 0x00; ++ data[25] = 0x08; ++ data[26] = 0x00; ++ data[27] = 0x0C; ++ data[28] = 0x00; ++ data[29] = 0x0C; ++ data[30] = 0x00; ++ data[31] = 0x0D; ++ data[32] = 0x00; ++ data[33] = 0x0F; ++ data[34] = 0x00; ++ data[35] = 0x0E; ++ data[36] = 0x00; ++ data[37] = 0x0E; ++ data[38] = 0x00; ++ data[39] = 0x10; ++ data[40] = 0x00; ++ data[41] = 0x0F; ++ data[42] = 0x00; ++ data[43] = 0x0E; ++ data[44] = 0x00; ++ data[45] = 0x10; ++ data[46] = 0x00; ++ data[47] = 0x0F; ++ data[48] = 0x00; ++ data[49] = 0x0E; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x12, data, ++ 50) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ CXD2880_SLEEP(1); ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x0A) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x10, data, ++ 1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if ((data[0] & 0x01) == 0x00) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x25, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ CXD2880_SLEEP(1); ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x0A) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x11, data, ++ 1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if ((data[0] & 0x01) == 0x00) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x02, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x21, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0xE1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x8F, ++ 0x16) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x67, ++ 0x60) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x6A, ++ 0x0F) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x6C, ++ 0x17) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ data[0] = 0x00; ++ data[1] = 0xFE; ++ data[2] = 0xEE; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x6E, data, ++ 3) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ data[0] = 0xA1; ++ data[1] = 0x8B; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x8D, data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ data[0] = 0x08; ++ data[1] = 0x09; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x77, data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->create_param.stationary_use) { ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x80, ++ 0xAA) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0xE2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x41, ++ 0xA0) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x4B, ++ 0x68) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x21, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x10, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x10) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x25, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ CXD2880_SLEEP(1); ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x1A) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x10, data, ++ 1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if ((data[0] & 0x01) == 0x00) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x10) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x14, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x26, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++static enum cxd2880_ret rf_init2(struct cxd2880_tnrdmd *tnr_dmd) ++{ ++ u8 data[5] = { 0 }; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x10) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ data[0] = 0x40; ++ data[1] = 0x40; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0xEA, data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ CXD2880_SLEEP(1); ++ ++ data[0] = 0x00; ++ if (tnr_dmd->chip_id == CXD2880_TNRDMD_CHIP_ID_CXD2880_ES1_0X) ++ data[1] = 0x00; ++ else ++ data[1] = 0x01; ++ data[2] = 0x01; ++ data[3] = 0x03; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x30, data, ++ 4) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x14) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x1B, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x21, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0xE1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xD3, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x21, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++static enum cxd2880_ret x_tune1(struct cxd2880_tnrdmd *tnr_dmd, ++ enum cxd2880_dtv_sys sys, u32 freq_khz, ++ enum cxd2880_dtv_bandwidth bandwidth, ++ u8 is_cable, int shift_frequency_khz) ++{ ++ u8 data[11] = { 0 }; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x10, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x10) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ data[0] = 0x00; ++ data[1] = 0x00; ++ data[2] = 0x0E; ++ data[3] = 0x00; ++ data[4] = 0x03; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0xE7, data, ++ 5) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ data[0] = 0x1F; ++ data[1] = 0x80; ++ data[2] = 0x18; ++ data[3] = 0x00; ++ data[4] = 0x07; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0xE7, data, ++ 5) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ CXD2880_SLEEP(1); ++ ++ data[0] = 0x72; ++ data[1] = 0x81; ++ data[3] = 0x1D; ++ data[4] = 0x6F; ++ data[5] = 0x7E; ++ data[7] = 0x1C; ++ switch (sys) { ++ case CXD2880_DTV_SYS_DVBT: ++ case CXD2880_DTV_SYS_ISDBT: ++ case CXD2880_DTV_SYS_ISDBTSB: ++ case CXD2880_DTV_SYS_ISDBTMM_A: ++ case CXD2880_DTV_SYS_ISDBTMM_B: ++ data[2] = 0x94; ++ data[6] = 0x91; ++ break; ++ case CXD2880_DTV_SYS_DVBT2: ++ data[2] = 0x96; ++ data[6] = 0x93; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_ARG; ++ } ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x44, data, ++ 8) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x62, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x15) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ data[0] = 0x03; ++ data[1] = 0xE2; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x1E, data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x10) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ data[0] = (u8)(is_cable ? 0x01 : 0x00); ++ data[1] = 0x00; ++ data[2] = 0x6B; ++ data[3] = 0x4D; ++ ++ switch (bandwidth) { ++ case CXD2880_DTV_BW_1_7_MHZ: ++ data[4] = 0x03; ++ break; ++ case CXD2880_DTV_BW_5_MHZ: ++ case CXD2880_DTV_BW_6_MHZ: ++ data[4] = 0x00; ++ break; ++ case CXD2880_DTV_BW_7_MHZ: ++ data[4] = 0x01; ++ break; ++ case CXD2880_DTV_BW_8_MHZ: ++ data[4] = 0x02; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_ARG; ++ } ++ ++ data[5] = 0x00; ++ ++ freq_khz += shift_frequency_khz; ++ ++ data[6] = (u8)((freq_khz >> 16) & 0x0F); ++ data[7] = (u8)((freq_khz >> 8) & 0xFF); ++ data[8] = (u8)(freq_khz & 0xFF); ++ data[9] = 0xFF; ++ data[10] = 0xFE; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x52, data, ++ 11) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++static enum cxd2880_ret x_tune2(struct cxd2880_tnrdmd *tnr_dmd, ++ enum cxd2880_dtv_bandwidth bandwidth, ++ enum cxd2880_tnrdmd_clockmode clk_mode, ++ int shift_frequency_khz) ++{ ++ u8 data[3] = { 0 }; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x11) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ data[0] = 0x01; ++ data[1] = 0x0E; ++ data[2] = 0x01; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x2D, data, ++ 3) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x1A) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x29, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x2C, data, ++ 1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x10) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x60, ++ data[0]) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x62, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x11) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x2D, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x2F, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x10, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x21, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (shift_frequency_khz != 0) { ++ int shift_freq = 0; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0xE1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x60, data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ shift_freq = shift_frequency_khz * 1000; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ default: ++ if (shift_freq >= 0) ++ shift_freq = (shift_freq + 183 / 2) / 183; ++ else ++ shift_freq = (shift_freq - 183 / 2) / 183; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ if (shift_freq >= 0) ++ shift_freq = (shift_freq + 178 / 2) / 178; ++ else ++ shift_freq = (shift_freq - 178 / 2) / 178; ++ break; ++ } ++ ++ shift_freq += ++ cxd2880_convert2s_complement((data[0] << 8) | data[1], 16); ++ ++ if (shift_freq > 32767) ++ shift_freq = 32767; ++ else if (shift_freq < -32768) ++ shift_freq = -32768; ++ ++ data[0] = (u8)(((u32)shift_freq >> 8) & 0xFF); ++ data[1] = (u8)((u32)shift_freq & 0xFF); ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x60, data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x69, data, ++ 1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ shift_freq = -shift_frequency_khz; ++ ++ if (bandwidth == CXD2880_DTV_BW_1_7_MHZ) { ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ default: ++ if (shift_freq >= 0) ++ shift_freq = ++ (shift_freq * 1000 + ++ 17578 / 2) / 17578; ++ else ++ shift_freq = ++ (shift_freq * 1000 - ++ 17578 / 2) / 17578; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ if (shift_freq >= 0) ++ shift_freq = ++ (shift_freq * 1000 + ++ 17090 / 2) / 17090; ++ else ++ shift_freq = ++ (shift_freq * 1000 - ++ 17090 / 2) / 17090; ++ break; ++ } ++ } else { ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ default: ++ if (shift_freq >= 0) ++ shift_freq = ++ (shift_freq * 1000 + ++ 35156 / 2) / 35156; ++ else ++ shift_freq = ++ (shift_freq * 1000 - ++ 35156 / 2) / 35156; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ if (shift_freq >= 0) ++ shift_freq = ++ (shift_freq * 1000 + ++ 34180 / 2) / 34180; ++ else ++ shift_freq = ++ (shift_freq * 1000 - ++ 34180 / 2) / 34180; ++ break; ++ } ++ } ++ ++ shift_freq += cxd2880_convert2s_complement(data[0], 8); ++ ++ if (shift_freq > 127) ++ shift_freq = 127; ++ else if (shift_freq < -128) ++ shift_freq = -128; ++ ++ data[0] = (u8)((u32)shift_freq & 0xFF); ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x69, ++ data[0]) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->create_param.stationary_use) { ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0xE1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x8A, ++ 0x87) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x21, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++static enum cxd2880_ret x_tune3(struct cxd2880_tnrdmd *tnr_dmd, ++ enum cxd2880_dtv_sys sys, ++ u8 en_fef_intmtnt_ctrl) ++{ ++ u8 data[6] = { 0 }; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x21, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0xE2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x41, ++ 0xA0) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x21, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xFE, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x10) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if ((sys == CXD2880_DTV_SYS_DVBT2) && en_fef_intmtnt_ctrl) { ++ data[0] = 0x01; ++ data[1] = 0x01; ++ data[2] = 0x01; ++ data[3] = 0x01; ++ data[4] = 0x01; ++ data[5] = 0x01; ++ } else { ++ data[0] = 0x00; ++ data[1] = 0x00; ++ data[2] = 0x00; ++ data[3] = 0x00; ++ data[4] = 0x00; ++ data[5] = 0x00; ++ } ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0xEF, data, ++ 6) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x2D) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if ((sys == CXD2880_DTV_SYS_DVBT2) && en_fef_intmtnt_ctrl) ++ data[0] = 0x00; ++ else ++ data[0] = 0x01; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xB1, ++ data[0]) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++static enum cxd2880_ret x_tune4(struct cxd2880_tnrdmd *tnr_dmd) ++{ ++ u8 data[2] = { 0 }; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ { ++ if (tnr_dmd->diver_sub->io->write_reg(tnr_dmd->diver_sub->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x00) != ++ CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ data[0] = 0x14; ++ data[1] = 0x00; ++ if (tnr_dmd->diver_sub->io->write_regs(tnr_dmd->diver_sub->io, ++ CXD2880_IO_TGT_SYS, 0x55, ++ data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ { ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ data[0] = 0x0B; ++ data[1] = 0xFF; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x53, data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x57, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ data[0] = 0x0B; ++ data[1] = 0xFF; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x55, data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ { ++ if (tnr_dmd->diver_sub->io->write_reg(tnr_dmd->diver_sub->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x00) != ++ CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ data[0] = 0x14; ++ data[1] = 0x00; ++ if (tnr_dmd->diver_sub->io->write_regs(tnr_dmd->diver_sub->io, ++ CXD2880_IO_TGT_SYS, 0x53, ++ data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->diver_sub->io->write_reg(tnr_dmd->diver_sub->io, ++ CXD2880_IO_TGT_SYS, 0x57, ++ 0x02) != ++ CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xFE, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->diver_sub->io->write_reg(tnr_dmd->diver_sub->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->diver_sub->io->write_reg(tnr_dmd->diver_sub->io, ++ CXD2880_IO_TGT_DMD, 0xFE, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++static enum cxd2880_ret x_sleep1(struct cxd2880_tnrdmd *tnr_dmd) ++{ ++ u8 data[3] = { 0 }; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ { ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x57, ++ 0x03) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ data[0] = 0x00; ++ data[1] = 0x00; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x53, data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ { ++ if (tnr_dmd->diver_sub->io->write_reg(tnr_dmd->diver_sub->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x00) != ++ CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ data[0] = 0x1F; ++ data[1] = 0xFF; ++ data[2] = 0x03; ++ if (tnr_dmd->diver_sub->io->write_regs(tnr_dmd->diver_sub->io, ++ CXD2880_IO_TGT_SYS, 0x55, ++ data, ++ 3) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ data[0] = 0x00; ++ data[1] = 0x00; ++ if (tnr_dmd->diver_sub->io->write_regs(tnr_dmd->diver_sub->io, ++ CXD2880_IO_TGT_SYS, 0x53, ++ data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ { ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ data[0] = 0x1F; ++ data[1] = 0xFF; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x55, data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ return CXD2880_RESULT_OK; ++} ++ ++static enum cxd2880_ret x_sleep2(struct cxd2880_tnrdmd *tnr_dmd) ++{ ++ u8 data = 0; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x2D) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xB1, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ CXD2880_SLEEP(1); ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xB2, &data, ++ 1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if ((data & 0x01) == 0x00) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x10) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0xF4, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0xF3, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0xF2, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0xF1, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0xF0, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0xEF, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++static enum cxd2880_ret x_sleep3(struct cxd2880_tnrdmd *tnr_dmd) ++{ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xFD, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++static enum cxd2880_ret x_sleep4(struct cxd2880_tnrdmd *tnr_dmd) ++{ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x21, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0xE2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x41, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x21, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++static enum cxd2880_ret spll_reset(struct cxd2880_tnrdmd *tnr_dmd, ++ enum cxd2880_tnrdmd_clockmode clockmode) ++{ ++ u8 data[4] = { 0 }; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x10) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x29, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x28, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x27, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x26, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x10, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x27, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x22, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ switch (clockmode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ data[0] = 0x00; ++ break; ++ ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data[0] = 0x01; ++ break; ++ ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data[0] = 0x02; ++ break; ++ ++ default: ++ return CXD2880_RESULT_ERROR_ARG; ++ } ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x30, ++ data[0]) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x22, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ CXD2880_SLEEP(2); ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x0A) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x10, data, ++ 1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if ((data[0] & 0x01) == 0x00) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x27, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ CXD2880_SLEEP(1); ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x10, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x10) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ data[0] = 0x00; ++ data[1] = 0x00; ++ data[2] = 0x00; ++ data[3] = 0x00; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x26, data, ++ 4) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++static enum cxd2880_ret t_power_x(struct cxd2880_tnrdmd *tnr_dmd, u8 on) ++{ ++ u8 data[3] = { 0 }; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x10) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x29, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x28, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x27, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x10, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x27, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x25, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (on) { ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x2B, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ CXD2880_SLEEP(1); ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x0A) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x12, data, ++ 1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if ((data[0] & 0x01) == 0) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x2A, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } else { ++ data[0] = 0x03; ++ data[1] = 0x00; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x2A, data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ CXD2880_SLEEP(1); ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x0A) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x13, data, ++ 1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if ((data[0] & 0x01) == 0) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x25, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ CXD2880_SLEEP(1); ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x0A) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x11, data, ++ 1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if ((data[0] & 0x01) == 0) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x27, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ CXD2880_SLEEP(1); ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x10, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x10) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ data[0] = 0x00; ++ data[1] = 0x00; ++ data[2] = 0x00; ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x27, data, ++ 3) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++struct cxd2880_tnrdmd_ts_clk_cfg { ++ u8 srl_clk_mode; ++ u8 srl_duty_mode; ++ u8 ts_clk_period; ++}; ++ ++static enum cxd2880_ret set_ts_clk_mode_and_freq(struct cxd2880_tnrdmd *tnr_dmd, ++ enum cxd2880_dtv_sys sys) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ u8 backwards_compatible = 0; ++ struct cxd2880_tnrdmd_ts_clk_cfg ts_clk_cfg; ++ ++ const struct cxd2880_tnrdmd_ts_clk_cfg srl_ts_clk_stgs[2][2] = { ++ { ++ {3, 1, 8,}, ++ {0, 2, 16,} ++ }, ++ { ++ {1, 1, 8,}, ++ {2, 2, 16,} ++ } ++ }; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ { ++ u8 ts_rate_ctrl_off = 0; ++ u8 ts_in_off = 0; ++ u8 ts_clk_manaul_on = 0; ++ ++ if ((sys == CXD2880_DTV_SYS_ISDBT) || ++ (sys == CXD2880_DTV_SYS_ISDBTSB) || ++ (sys == CXD2880_DTV_SYS_ISDBTMM_A) || ++ (sys == CXD2880_DTV_SYS_ISDBTMM_B)) { ++ backwards_compatible = 0; ++ ts_rate_ctrl_off = 1; ++ ts_in_off = 0; ++ } else if (tnr_dmd->is_ts_backwards_compatible_mode) { ++ backwards_compatible = 1; ++ ts_rate_ctrl_off = 1; ++ ts_in_off = 1; ++ } else { ++ backwards_compatible = 0; ++ ts_rate_ctrl_off = 0; ++ ts_in_off = 0; ++ } ++ ++ if (tnr_dmd->ts_byte_clk_manual_setting) { ++ ts_clk_manaul_on = 1; ++ ts_rate_ctrl_off = 0; ++ } ++ ++ ret = ++ cxd2880_io_set_reg_bits(tnr_dmd->io, CXD2880_IO_TGT_DMD, ++ 0xD3, ts_rate_ctrl_off, 0x01); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ ret = ++ cxd2880_io_set_reg_bits(tnr_dmd->io, CXD2880_IO_TGT_DMD, ++ 0xDE, ts_in_off, 0x01); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ ret = ++ cxd2880_io_set_reg_bits(tnr_dmd->io, CXD2880_IO_TGT_DMD, ++ 0xDA, ts_clk_manaul_on, 0x01); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ ts_clk_cfg = ++ srl_ts_clk_stgs[tnr_dmd->srl_ts_clk_mod_cnts] ++ [(u8)tnr_dmd->srl_ts_clk_frq]; ++ ++ if (tnr_dmd->ts_byte_clk_manual_setting) ++ ts_clk_cfg.ts_clk_period = tnr_dmd->ts_byte_clk_manual_setting; ++ ++ ret = ++ cxd2880_io_set_reg_bits(tnr_dmd->io, CXD2880_IO_TGT_DMD, 0xC4, ++ ts_clk_cfg.srl_clk_mode, 0x03); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ ret = ++ cxd2880_io_set_reg_bits(tnr_dmd->io, CXD2880_IO_TGT_DMD, 0xD1, ++ ts_clk_cfg.srl_duty_mode, 0x03); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ ret = tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xD9, ++ ts_clk_cfg.ts_clk_period); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ { ++ u8 data = (u8)(backwards_compatible ? 0x00 : 0x01); ++ ++ if (sys == CXD2880_DTV_SYS_DVBT) { ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x10) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ ret = ++ cxd2880_io_set_reg_bits(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x66, ++ data, 0x01); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ } ++ ++ return ret; ++} ++ ++static enum cxd2880_ret pid_ftr_setting(struct cxd2880_tnrdmd *tnr_dmd, ++ struct cxd2880_tnrdmd_pid_ftr_cfg ++ *pid_ftr_cfg) ++{ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (!pid_ftr_cfg) { ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x50, ++ 0x02) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } else { ++ u8 data[65]; ++ ++ data[0] = (u8)(pid_ftr_cfg->is_negative ? 0x01 : 0x00); ++ { ++ int i = 0; ++ ++ for (i = 0; i < 32; i++) { ++ if (pid_ftr_cfg->pid_cfg[i].is_en) { ++ data[1 + (i * 2)] = ++ (u8)((u8) ++ (pid_ftr_cfg->pid_cfg[i].pid ++ >> 8) | 0x20); ++ data[2 + (i * 2)] = ++ (u8)(pid_ftr_cfg->pid_cfg[i].pid ++ & 0xFF); ++ } else { ++ data[1 + (i * 2)] = 0x00; ++ data[2 + (i * 2)] = 0x00; ++ } ++ } ++ } ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x50, data, ++ 65) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ return CXD2880_RESULT_OK; ++} ++ ++static enum cxd2880_ret load_cfg_mem(struct cxd2880_tnrdmd *tnr_dmd) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ u8 i; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ for (i = 0; i < tnr_dmd->cfg_mem_last_entry; i++) { ++ ret = tnr_dmd->io->write_reg(tnr_dmd->io, ++ tnr_dmd->cfg_mem[i].tgt, ++ 0x00, tnr_dmd->cfg_mem[i].bank); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ ret = cxd2880_io_set_reg_bits(tnr_dmd->io, ++ tnr_dmd->cfg_mem[i].tgt, ++ tnr_dmd->cfg_mem[i].address, ++ tnr_dmd->cfg_mem[i].value, ++ tnr_dmd->cfg_mem[i].bit_mask); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ return ret; ++} ++ ++static enum cxd2880_ret set_cfg_mem(struct cxd2880_tnrdmd *tnr_dmd, ++ enum cxd2880_io_tgt tgt, ++ u8 bank, u8 address, u8 value, u8 bit_mask) ++{ ++ u8 i; ++ u8 value_stored = 0; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ for (i = 0; i < tnr_dmd->cfg_mem_last_entry; i++) { ++ if ((value_stored == 0) && ++ (tnr_dmd->cfg_mem[i].tgt == tgt) && ++ (tnr_dmd->cfg_mem[i].bank == bank) && ++ (tnr_dmd->cfg_mem[i].address == address)) { ++ tnr_dmd->cfg_mem[i].value &= ~bit_mask; ++ tnr_dmd->cfg_mem[i].value |= (value & bit_mask); ++ ++ tnr_dmd->cfg_mem[i].bit_mask |= bit_mask; ++ ++ value_stored = 1; ++ } ++ } ++ ++ if (value_stored == 0) { ++ if (tnr_dmd->cfg_mem_last_entry < ++ CXD2880_TNRDMD_MAX_CFG_MEM_COUNT) { ++ tnr_dmd->cfg_mem[tnr_dmd->cfg_mem_last_entry].tgt = tgt; ++ tnr_dmd->cfg_mem[tnr_dmd->cfg_mem_last_entry].bank = ++ bank; ++ tnr_dmd->cfg_mem[tnr_dmd->cfg_mem_last_entry].address = ++ address; ++ tnr_dmd->cfg_mem[tnr_dmd->cfg_mem_last_entry].value = ++ (value & bit_mask); ++ tnr_dmd->cfg_mem[tnr_dmd->cfg_mem_last_entry].bit_mask = ++ bit_mask; ++ tnr_dmd->cfg_mem_last_entry++; ++ } else { ++ return CXD2880_RESULT_ERROR_OVERFLOW; ++ } ++ } ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_create(struct cxd2880_tnrdmd *tnr_dmd, ++ struct cxd2880_io *io, ++ struct cxd2880_tnrdmd_create_param ++ *create_param) ++{ ++ if ((!tnr_dmd) || (!io) || (!create_param)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ cxd2880_memset(tnr_dmd, 0, sizeof(struct cxd2880_tnrdmd)); ++ ++ tnr_dmd->io = io; ++ tnr_dmd->create_param = *create_param; ++ ++ tnr_dmd->diver_mode = CXD2880_TNRDMD_DIVERMODE_SINGLE; ++ tnr_dmd->diver_sub = NULL; ++ ++ tnr_dmd->srl_ts_clk_mod_cnts = 1; ++ tnr_dmd->en_fef_intmtnt_base = 1; ++ tnr_dmd->en_fef_intmtnt_lite = 1; ++ tnr_dmd->rf_lvl_cmpstn = NULL; ++ tnr_dmd->lna_thrs_tbl_air = NULL; ++ tnr_dmd->lna_thrs_tbl_cable = NULL; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_diver_create(struct cxd2880_tnrdmd ++ *tnr_dmd_main, ++ struct cxd2880_io *io_main, ++ struct cxd2880_tnrdmd *tnr_dmd_sub, ++ struct cxd2880_io *io_sub, ++ struct ++ cxd2880_tnrdmd_diver_create_param ++ *create_param) ++{ ++ if ((!tnr_dmd_main) || (!io_main) || (!tnr_dmd_sub) || (!io_sub) || ++ (!create_param)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ cxd2880_memset(tnr_dmd_main, 0, sizeof(struct cxd2880_tnrdmd)); ++ cxd2880_memset(tnr_dmd_sub, 0, sizeof(struct cxd2880_tnrdmd)); ++ ++ tnr_dmd_main->io = io_main; ++ tnr_dmd_main->diver_mode = CXD2880_TNRDMD_DIVERMODE_MAIN; ++ tnr_dmd_main->diver_sub = tnr_dmd_sub; ++ tnr_dmd_main->create_param.en_internal_ldo = ++ create_param->en_internal_ldo; ++ tnr_dmd_main->create_param.ts_output_if = create_param->ts_output_if; ++ tnr_dmd_main->create_param.xtal_share_type = ++ CXD2880_TNRDMD_XTAL_SHARE_MASTER; ++ tnr_dmd_main->create_param.xosc_cap = create_param->xosc_cap_main; ++ tnr_dmd_main->create_param.xosc_i = create_param->xosc_i_main; ++ tnr_dmd_main->create_param.is_cxd2881gg = create_param->is_cxd2881gg; ++ tnr_dmd_main->create_param.stationary_use = ++ create_param->stationary_use; ++ ++ tnr_dmd_sub->io = io_sub; ++ tnr_dmd_sub->diver_mode = CXD2880_TNRDMD_DIVERMODE_SUB; ++ tnr_dmd_sub->diver_sub = NULL; ++ tnr_dmd_sub->create_param.en_internal_ldo = ++ create_param->en_internal_ldo; ++ tnr_dmd_sub->create_param.ts_output_if = create_param->ts_output_if; ++ tnr_dmd_sub->create_param.xtal_share_type = ++ CXD2880_TNRDMD_XTAL_SHARE_SLAVE; ++ tnr_dmd_sub->create_param.xosc_cap = 0; ++ tnr_dmd_sub->create_param.xosc_i = create_param->xosc_i_sub; ++ tnr_dmd_sub->create_param.is_cxd2881gg = create_param->is_cxd2881gg; ++ tnr_dmd_sub->create_param.stationary_use = create_param->stationary_use; ++ ++ tnr_dmd_main->srl_ts_clk_mod_cnts = 1; ++ tnr_dmd_main->en_fef_intmtnt_base = 1; ++ tnr_dmd_main->en_fef_intmtnt_lite = 1; ++ tnr_dmd_main->rf_lvl_cmpstn = NULL; ++ tnr_dmd_main->lna_thrs_tbl_air = NULL; ++ tnr_dmd_main->lna_thrs_tbl_cable = NULL; ++ ++ tnr_dmd_sub->srl_ts_clk_mod_cnts = 1; ++ tnr_dmd_sub->en_fef_intmtnt_base = 1; ++ tnr_dmd_sub->en_fef_intmtnt_lite = 1; ++ tnr_dmd_sub->rf_lvl_cmpstn = NULL; ++ tnr_dmd_sub->lna_thrs_tbl_air = NULL; ++ tnr_dmd_sub->lna_thrs_tbl_cable = NULL; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_init1(struct cxd2880_tnrdmd *tnr_dmd) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ tnr_dmd->chip_id = CXD2880_TNRDMD_CHIP_ID_UNKNOWN; ++ tnr_dmd->state = CXD2880_TNRDMD_STATE_UNKNOWN; ++ tnr_dmd->clk_mode = CXD2880_TNRDMD_CLOCKMODE_UNKNOWN; ++ tnr_dmd->frequency_khz = 0; ++ tnr_dmd->sys = CXD2880_DTV_SYS_UNKNOWN; ++ tnr_dmd->bandwidth = CXD2880_DTV_BW_UNKNOWN; ++ tnr_dmd->scan_mode = 0; ++ cxd2880_atomic_set(&tnr_dmd->cancel, 0); ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ tnr_dmd->diver_sub->chip_id = CXD2880_TNRDMD_CHIP_ID_UNKNOWN; ++ tnr_dmd->diver_sub->state = CXD2880_TNRDMD_STATE_UNKNOWN; ++ tnr_dmd->diver_sub->clk_mode = CXD2880_TNRDMD_CLOCKMODE_UNKNOWN; ++ tnr_dmd->diver_sub->frequency_khz = 0; ++ tnr_dmd->diver_sub->sys = CXD2880_DTV_SYS_UNKNOWN; ++ tnr_dmd->diver_sub->bandwidth = CXD2880_DTV_BW_UNKNOWN; ++ tnr_dmd->diver_sub->scan_mode = 0; ++ cxd2880_atomic_set(&tnr_dmd->diver_sub->cancel, 0); ++ } ++ ++ ret = cxd2880_tnrdmd_chip_id(tnr_dmd, &tnr_dmd->chip_id); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (!CXD2880_TNRDMD_CHIP_ID_VALID(tnr_dmd->chip_id)) ++ return CXD2880_RESULT_ERROR_NOSUPPORT; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ ret = ++ cxd2880_tnrdmd_chip_id(tnr_dmd->diver_sub, ++ &tnr_dmd->diver_sub->chip_id); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (!CXD2880_TNRDMD_CHIP_ID_VALID(tnr_dmd->diver_sub->chip_id)) ++ return CXD2880_RESULT_ERROR_NOSUPPORT; ++ } ++ ++ ret = p_init1(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ ret = p_init1(tnr_dmd->diver_sub); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ CXD2880_SLEEP(1); ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ ret = p_init2(tnr_dmd->diver_sub); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ ret = p_init2(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ CXD2880_SLEEP(5); ++ ++ ret = p_init3(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ ret = p_init3(tnr_dmd->diver_sub); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ ret = rf_init1(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ ret = rf_init1(tnr_dmd->diver_sub); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_init2(struct cxd2880_tnrdmd *tnr_dmd) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ { ++ u8 cpu_task_completed = 0; ++ ++ ret = ++ cxd2880_tnrdmd_check_internal_cpu_status(tnr_dmd, ++ &cpu_task_completed); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (!cpu_task_completed) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ ++ ret = rf_init2(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ ret = rf_init2(tnr_dmd->diver_sub); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ ret = load_cfg_mem(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ ret = load_cfg_mem(tnr_dmd->diver_sub); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ tnr_dmd->state = CXD2880_TNRDMD_STATE_SLEEP; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) ++ tnr_dmd->diver_sub->state = CXD2880_TNRDMD_STATE_SLEEP; ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_check_internal_cpu_status(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ u8 *task_completed) ++{ ++ u16 cpu_status = 0; ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!task_completed)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ ret = cxd2880_tnrdmd_mon_internal_cpu_status(tnr_dmd, &cpu_status); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE) { ++ if (cpu_status == 0) ++ *task_completed = 1; ++ else ++ *task_completed = 0; ++ ++ return ret; ++ } ++ if (cpu_status != 0) { ++ *task_completed = 0; ++ return ret; ++ } ++ ++ ret = cxd2880_tnrdmd_mon_internal_cpu_status_sub(tnr_dmd, &cpu_status); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (cpu_status == 0) ++ *task_completed = 1; ++ else ++ *task_completed = 0; ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_common_tune_setting1(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum cxd2880_dtv_sys sys, ++ u32 frequency_khz, ++ enum cxd2880_dtv_bandwidth ++ bandwidth, u8 one_seg_opt, ++ u8 one_seg_opt_shft_dir) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) && ++ (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (frequency_khz < 4000) ++ return CXD2880_RESULT_ERROR_RANGE; ++ ++ ret = cxd2880_tnrdmd_sleep(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ { ++ u8 data = 0; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x2B, &data, ++ 1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ switch (sys) { ++ case CXD2880_DTV_SYS_DVBT: ++ case CXD2880_DTV_SYS_ISDBT: ++ case CXD2880_DTV_SYS_ISDBTSB: ++ case CXD2880_DTV_SYS_ISDBTMM_A: ++ case CXD2880_DTV_SYS_ISDBTMM_B: ++ if (data == 0x00) { ++ ret = t_power_x(tnr_dmd, 1); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (tnr_dmd->diver_mode == ++ CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ ret = t_power_x(tnr_dmd->diver_sub, 1); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ } ++ break; ++ ++ case CXD2880_DTV_SYS_DVBT2: ++ if (data == 0x01) { ++ ret = t_power_x(tnr_dmd, 0); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (tnr_dmd->diver_mode == ++ CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ ret = t_power_x(tnr_dmd->diver_sub, 0); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ } ++ break; ++ ++ default: ++ return CXD2880_RESULT_ERROR_ARG; ++ } ++ } ++ ++ { ++ enum cxd2880_tnrdmd_clockmode new_clk_mode = ++ CXD2880_TNRDMD_CLOCKMODE_A; ++ ++ ret = spll_reset(tnr_dmd, new_clk_mode); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ tnr_dmd->clk_mode = new_clk_mode; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ ret = spll_reset(tnr_dmd->diver_sub, new_clk_mode); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ tnr_dmd->diver_sub->clk_mode = new_clk_mode; ++ } ++ ++ ret = load_cfg_mem(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ ret = load_cfg_mem(tnr_dmd->diver_sub); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ } ++ ++ { ++ int shift_frequency_khz = 0; ++ ++ if (one_seg_opt) { ++ if (tnr_dmd->diver_mode == ++ CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ shift_frequency_khz = 350; ++ } else { ++ if (one_seg_opt_shft_dir) ++ shift_frequency_khz = 350; ++ else ++ shift_frequency_khz = -350; ++ ++ if (tnr_dmd->create_param.xtal_share_type == ++ CXD2880_TNRDMD_XTAL_SHARE_SLAVE) ++ shift_frequency_khz *= -1; ++ } ++ } else { ++ if (tnr_dmd->diver_mode == ++ CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ shift_frequency_khz = 150; ++ } else { ++ switch (tnr_dmd->create_param.xtal_share_type) { ++ case CXD2880_TNRDMD_XTAL_SHARE_NONE: ++ case CXD2880_TNRDMD_XTAL_SHARE_EXTREF: ++ default: ++ shift_frequency_khz = 0; ++ break; ++ case CXD2880_TNRDMD_XTAL_SHARE_MASTER: ++ shift_frequency_khz = 150; ++ break; ++ case CXD2880_TNRDMD_XTAL_SHARE_SLAVE: ++ shift_frequency_khz = -150; ++ break; ++ } ++ } ++ } ++ ++ ret = ++ x_tune1(tnr_dmd, sys, frequency_khz, bandwidth, ++ tnr_dmd->is_cable_input, shift_frequency_khz); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ ret = ++ x_tune1(tnr_dmd->diver_sub, sys, frequency_khz, ++ bandwidth, tnr_dmd->is_cable_input, ++ -shift_frequency_khz); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ CXD2880_SLEEP(10); ++ ++ { ++ u8 cpu_task_completed = 0; ++ ++ ret = ++ cxd2880_tnrdmd_check_internal_cpu_status(tnr_dmd, ++ &cpu_task_completed); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (!cpu_task_completed) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ ++ ret = ++ x_tune2(tnr_dmd, bandwidth, tnr_dmd->clk_mode, ++ shift_frequency_khz); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ ret = ++ x_tune2(tnr_dmd->diver_sub, bandwidth, ++ tnr_dmd->diver_sub->clk_mode, ++ -shift_frequency_khz); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ } ++ ++ if (tnr_dmd->create_param.ts_output_if == CXD2880_TNRDMD_TSOUT_IF_TS) { ++ ret = set_ts_clk_mode_and_freq(tnr_dmd, sys); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } else { ++ struct cxd2880_tnrdmd_pid_ftr_cfg *pid_ftr_cfg; ++ ++ if (tnr_dmd->pid_ftr_cfg_en) ++ pid_ftr_cfg = &tnr_dmd->pid_ftr_cfg; ++ else ++ pid_ftr_cfg = NULL; ++ ++ ret = pid_ftr_setting(tnr_dmd, pid_ftr_cfg); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_common_tune_setting2(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum cxd2880_dtv_sys sys, ++ u8 en_fef_intmtnt_ctrl) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) && ++ (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = x_tune3(tnr_dmd, sys, en_fef_intmtnt_ctrl); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ ret = x_tune3(tnr_dmd->diver_sub, sys, en_fef_intmtnt_ctrl); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ ret = x_tune4(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ ret = cxd2880_tnrdmd_set_ts_output(tnr_dmd, 1); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_sleep(struct cxd2880_tnrdmd *tnr_dmd) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state == CXD2880_TNRDMD_STATE_SLEEP) { ++ } else if (tnr_dmd->state == CXD2880_TNRDMD_STATE_ACTIVE) { ++ ret = cxd2880_tnrdmd_set_ts_output(tnr_dmd, 0); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ ret = x_sleep1(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ ret = x_sleep2(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ ret = x_sleep2(tnr_dmd->diver_sub); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ switch (tnr_dmd->sys) { ++ case CXD2880_DTV_SYS_DVBT: ++ ret = cxd2880_tnrdmd_dvbt_sleep_setting(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ break; ++ ++ case CXD2880_DTV_SYS_DVBT2: ++ ret = cxd2880_tnrdmd_dvbt2_sleep_setting(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ break; ++ ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ ret = x_sleep3(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ ret = x_sleep3(tnr_dmd->diver_sub); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ ret = x_sleep4(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ ret = x_sleep4(tnr_dmd->diver_sub); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ tnr_dmd->state = CXD2880_TNRDMD_STATE_SLEEP; ++ tnr_dmd->frequency_khz = 0; ++ tnr_dmd->sys = CXD2880_DTV_SYS_UNKNOWN; ++ tnr_dmd->bandwidth = CXD2880_DTV_BW_UNKNOWN; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ tnr_dmd->diver_sub->state = CXD2880_TNRDMD_STATE_SLEEP; ++ tnr_dmd->diver_sub->frequency_khz = 0; ++ tnr_dmd->diver_sub->sys = CXD2880_DTV_SYS_UNKNOWN; ++ tnr_dmd->diver_sub->bandwidth = CXD2880_DTV_BW_UNKNOWN; ++ } ++ } else { ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_set_cfg(struct cxd2880_tnrdmd *tnr_dmd, ++ enum cxd2880_tnrdmd_cfg_id id, ++ int value) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ u8 data[2] = { 0 }; ++ u8 need_sub_setting = 0; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) && ++ (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ switch (id) { ++ case CXD2880_TNRDMD_CFG_OUTPUT_SEL_MSB: ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_DMD, ++ 0x00, 0xC4, ++ (u8)(value ? 0x00 : ++ 0x10), 0x10); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ break; ++ ++ case CXD2880_TNRDMD_CFG_TSVALID_ACTIVE_HI: ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_DMD, ++ 0x00, 0xC5, ++ (u8)(value ? 0x00 : ++ 0x02), 0x02); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ break; ++ ++ case CXD2880_TNRDMD_CFG_TSSYNC_ACTIVE_HI: ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_DMD, ++ 0x00, 0xC5, ++ (u8)(value ? 0x00 : ++ 0x04), 0x04); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ break; ++ ++ case CXD2880_TNRDMD_CFG_TSERR_ACTIVE_HI: ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_DMD, ++ 0x00, 0xCB, ++ (u8)(value ? 0x00 : ++ 0x01), 0x01); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ break; ++ ++ case CXD2880_TNRDMD_CFG_LATCH_ON_POSEDGE: ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_DMD, ++ 0x00, 0xC5, ++ (u8)(value ? 0x01 : ++ 0x00), 0x01); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ break; ++ ++ case CXD2880_TNRDMD_CFG_TSCLK_CONT: ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ tnr_dmd->srl_ts_clk_mod_cnts = (u8)(value ? 0x01 : 0x00); ++ break; ++ ++ case CXD2880_TNRDMD_CFG_TSCLK_MASK: ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if ((value < 0) || (value > 0x1F)) ++ return CXD2880_RESULT_ERROR_RANGE; ++ ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_DMD, ++ 0x00, 0xC6, (u8)value, ++ 0x1F); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ break; ++ ++ case CXD2880_TNRDMD_CFG_TSVALID_MASK: ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if ((value < 0) || (value > 0x1F)) ++ return CXD2880_RESULT_ERROR_RANGE; ++ ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_DMD, ++ 0x00, 0xC8, (u8)value, ++ 0x1F); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ break; ++ ++ case CXD2880_TNRDMD_CFG_TSERR_MASK: ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if ((value < 0) || (value > 0x1F)) ++ return CXD2880_RESULT_ERROR_RANGE; ++ ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_DMD, ++ 0x00, 0xC9, (u8)value, ++ 0x1F); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ break; ++ ++ case CXD2880_TNRDMD_CFG_TSERR_VALID_DIS: ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_DMD, ++ 0x00, 0x91, ++ (u8)(value ? 0x01 : ++ 0x00), 0x01); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ break; ++ ++ case CXD2880_TNRDMD_CFG_TSPIN_CURRENT: ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_SYS, ++ 0x00, 0x51, (u8)value, ++ 0x3F); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ break; ++ ++ case CXD2880_TNRDMD_CFG_TSPIN_PULLUP_MANUAL: ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_SYS, ++ 0x00, 0x50, ++ (u8)(value ? 0x80 : ++ 0x00), 0x80); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ break; ++ ++ case CXD2880_TNRDMD_CFG_TSPIN_PULLUP: ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_SYS, ++ 0x00, 0x50, (u8)value, ++ 0x3F); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ break; ++ ++ case CXD2880_TNRDMD_CFG_TSCLK_FREQ: ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if ((value < 0) || (value > 1)) ++ return CXD2880_RESULT_ERROR_RANGE; ++ ++ tnr_dmd->srl_ts_clk_frq = ++ (enum cxd2880_tnrdmd_serial_ts_clk)value; ++ break; ++ ++ case CXD2880_TNRDMD_CFG_TSBYTECLK_MANUAL: ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if ((value < 0) || (value > 0xFF)) ++ return CXD2880_RESULT_ERROR_RANGE; ++ ++ tnr_dmd->ts_byte_clk_manual_setting = (u8)value; ++ ++ break; ++ ++ case CXD2880_TNRDMD_CFG_TS_PACKET_GAP: ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if ((value < 0) || (value > 7)) ++ return CXD2880_RESULT_ERROR_RANGE; ++ ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_DMD, ++ 0x00, 0xD6, (u8)value, ++ 0x07); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ break; ++ ++ case CXD2880_TNRDMD_CFG_TS_BACKWARDS_COMPATIBLE: ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ tnr_dmd->is_ts_backwards_compatible_mode = (u8)(value ? 1 : 0); ++ ++ break; ++ ++ case CXD2880_TNRDMD_CFG_PWM_VALUE: ++ if ((value < 0) || (value > 0x1000)) ++ return CXD2880_RESULT_ERROR_RANGE; ++ ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_DMD, ++ 0x00, 0x22, ++ (u8)(value ? 0x01 : ++ 0x00), 0x01); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ { ++ u8 data[2]; ++ ++ data[0] = (u8)(((u16)value >> 8) & 0x1F); ++ data[1] = (u8)((u16)value & 0xFF); ++ ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_DMD, ++ 0x00, 0x23, ++ data[0], 0x1F); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_DMD, ++ 0x00, 0x24, ++ data[1], 0xFF); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ break; ++ ++ case CXD2880_TNRDMD_CFG_INTERRUPT: ++ data[0] = (u8)((value >> 8) & 0xFF); ++ data[1] = (u8)(value & 0xFF); ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_SYS, ++ 0x00, 0x48, data[0], ++ 0xFF); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_SYS, ++ 0x00, 0x49, data[1], ++ 0xFF); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ break; ++ ++ case CXD2880_TNRDMD_CFG_INTERRUPT_LOCK_SEL: ++ data[0] = (u8)(value & 0x07); ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_SYS, ++ 0x00, 0x4A, data[0], ++ 0x07); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ break; ++ ++ case CXD2880_TNRDMD_CFG_INTERRUPT_INV_LOCK_SEL: ++ data[0] = (u8)((value & 0x07) << 3); ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_SYS, ++ 0x00, 0x4A, data[0], ++ 0x38); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ break; ++ ++ case CXD2880_TNRDMD_CFG_FIXED_CLOCKMODE: ++ if ((value < (int)CXD2880_TNRDMD_CLOCKMODE_UNKNOWN) || ++ (value > (int)CXD2880_TNRDMD_CLOCKMODE_C)) ++ return CXD2880_RESULT_ERROR_RANGE; ++ tnr_dmd->fixed_clk_mode = (enum cxd2880_tnrdmd_clockmode)value; ++ break; ++ ++ case CXD2880_TNRDMD_CFG_CABLE_INPUT: ++ tnr_dmd->is_cable_input = (u8)(value ? 1 : 0); ++ break; ++ ++ case CXD2880_TNRDMD_CFG_DVBT2_FEF_INTERMITTENT_BASE: ++ tnr_dmd->en_fef_intmtnt_base = (u8)(value ? 1 : 0); ++ break; ++ ++ case CXD2880_TNRDMD_CFG_DVBT2_FEF_INTERMITTENT_LITE: ++ tnr_dmd->en_fef_intmtnt_lite = (u8)(value ? 1 : 0); ++ break; ++ ++ case CXD2880_TNRDMD_CFG_TS_BUF_ALMOST_EMPTY_THRS: ++ data[0] = (u8)((value >> 8) & 0x07); ++ data[1] = (u8)(value & 0xFF); ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_DMD, ++ 0x00, 0x99, data[0], ++ 0x07); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_DMD, ++ 0x00, 0x9A, data[1], ++ 0xFF); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ break; ++ ++ case CXD2880_TNRDMD_CFG_TS_BUF_ALMOST_FULL_THRS: ++ data[0] = (u8)((value >> 8) & 0x07); ++ data[1] = (u8)(value & 0xFF); ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_DMD, ++ 0x00, 0x9B, data[0], ++ 0x07); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_DMD, ++ 0x00, 0x9C, data[1], ++ 0xFF); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ break; ++ ++ case CXD2880_TNRDMD_CFG_TS_BUF_RRDY_THRS: ++ data[0] = (u8)((value >> 8) & 0x07); ++ data[1] = (u8)(value & 0xFF); ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_DMD, ++ 0x00, 0x9D, data[0], ++ 0x07); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_DMD, ++ 0x00, 0x9E, data[1], ++ 0xFF); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ break; ++ ++ case CXD2880_TNRDMD_CFG_BLINDTUNE_DVBT2_FIRST: ++ tnr_dmd->blind_tune_dvbt2_first = (u8)(value ? 1 : 0); ++ break; ++ ++ case CXD2880_TNRDMD_CFG_DVBT_BERN_PERIOD: ++ if ((value < 0) || (value > 31)) ++ return CXD2880_RESULT_ERROR_RANGE; ++ ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_DMD, ++ 0x10, 0x60, ++ (u8)(value & 0x1F), ++ 0x1F); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ break; ++ ++ case CXD2880_TNRDMD_CFG_DVBT_VBER_PERIOD: ++ if ((value < 0) || (value > 7)) ++ return CXD2880_RESULT_ERROR_RANGE; ++ ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_DMD, ++ 0x10, 0x6F, ++ (u8)(value & 0x07), ++ 0x07); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ break; ++ ++ case CXD2880_TNRDMD_CFG_DVBT2_BBER_MES: ++ if ((value < 0) || (value > 15)) ++ return CXD2880_RESULT_ERROR_RANGE; ++ ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_DMD, ++ 0x20, 0x72, ++ (u8)(value & 0x0F), ++ 0x0F); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ break; ++ ++ case CXD2880_TNRDMD_CFG_DVBT2_LBER_MES: ++ if ((value < 0) || (value > 15)) ++ return CXD2880_RESULT_ERROR_RANGE; ++ ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_DMD, ++ 0x20, 0x6F, ++ (u8)(value & 0x0F), ++ 0x0F); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ break; ++ ++ case CXD2880_TNRDMD_CFG_DVBT_PER_MES: ++ if ((value < 0) || (value > 15)) ++ return CXD2880_RESULT_ERROR_RANGE; ++ ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_DMD, ++ 0x10, 0x5C, ++ (u8)(value & 0x0F), ++ 0x0F); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ break; ++ ++ case CXD2880_TNRDMD_CFG_DVBT2_PER_MES: ++ if ((value < 0) || (value > 15)) ++ return CXD2880_RESULT_ERROR_RANGE; ++ ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_DMD, ++ 0x24, 0xDC, ++ (u8)(value & 0x0F), ++ 0x0F); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ break; ++ ++ case CXD2880_TNRDMD_CFG_ISDBT_BERPER_PERIOD: ++ { ++ u8 data[2]; ++ ++ data[0] = (u8)((value & 0x00007F00) >> 8); ++ data[1] = (u8)(value & 0x000000FF); ++ ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_DMD, ++ 0x60, 0x5B, ++ data[0], 0x7F); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, ++ CXD2880_IO_TGT_DMD, ++ 0x60, 0x5C, ++ data[1], 0xFF); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ break; ++ ++ default: ++ return CXD2880_RESULT_ERROR_ARG; ++ } ++ ++ if (need_sub_setting && ++ (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN)) { ++ ret = cxd2880_tnrdmd_set_cfg(tnr_dmd->diver_sub, id, value); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_gpio_set_cfg(struct cxd2880_tnrdmd *tnr_dmd, ++ u8 id, ++ u8 en, ++ enum cxd2880_tnrdmd_gpio_mode mode, ++ u8 open_drain, u8 invert) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (id > 2) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (mode > CXD2880_TNRDMD_GPIO_MODE_EEW) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) && ++ (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, CXD2880_IO_TGT_SYS, ++ 0x00, 0x40 + id, (u8)mode, ++ 0x0F); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, CXD2880_IO_TGT_SYS, ++ 0x00, 0x43, ++ (u8)(open_drain ? (1 << id) : ++ 0), (u8)(1 << id)); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, CXD2880_IO_TGT_SYS, ++ 0x00, 0x44, ++ (u8)(invert ? (1 << id) : 0), ++ (u8)(1 << id)); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, CXD2880_IO_TGT_SYS, ++ 0x00, 0x45, ++ (u8)(en ? 0 : (1 << id)), ++ (u8)(1 << id)); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_gpio_set_cfg_sub(struct cxd2880_tnrdmd *tnr_dmd, ++ u8 id, ++ u8 en, ++ enum cxd2880_tnrdmd_gpio_mode ++ mode, u8 open_drain, u8 invert) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ ret = ++ cxd2880_tnrdmd_gpio_set_cfg(tnr_dmd->diver_sub, id, en, mode, ++ open_drain, invert); ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_gpio_read(struct cxd2880_tnrdmd *tnr_dmd, ++ u8 id, u8 *value) ++{ ++ u8 data = 0; ++ ++ if ((!tnr_dmd) || (!value)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (id > 2) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) && ++ (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x0A) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x20, &data, ++ 1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ *value = (u8)((data >> id) & 0x01); ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_gpio_read_sub(struct cxd2880_tnrdmd *tnr_dmd, ++ u8 id, u8 *value) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ ret = cxd2880_tnrdmd_gpio_read(tnr_dmd->diver_sub, id, value); ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_gpio_write(struct cxd2880_tnrdmd *tnr_dmd, ++ u8 id, u8 value) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (id > 2) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) && ++ (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = ++ cxd2880_tnrdmd_set_and_save_reg_bits(tnr_dmd, CXD2880_IO_TGT_SYS, ++ 0x00, 0x46, ++ (u8)(value ? (1 << id) : 0), ++ (u8)(1 << id)); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_gpio_write_sub(struct cxd2880_tnrdmd *tnr_dmd, ++ u8 id, u8 value) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ ret = cxd2880_tnrdmd_gpio_write(tnr_dmd->diver_sub, id, value); ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_interrupt_read(struct cxd2880_tnrdmd *tnr_dmd, ++ u16 *value) ++{ ++ u8 data[2] = { 0 }; ++ ++ if ((!tnr_dmd) || (!value)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) && ++ (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x0A) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x15, data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ *value = (u16)(((u16)data[0] << 8) | (data[1])); ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_interrupt_clear(struct cxd2880_tnrdmd *tnr_dmd, ++ u16 value) ++{ ++ u8 data[2] = { 0 }; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) && ++ (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ data[0] = (u8)((value >> 8) & 0xFF); ++ data[1] = (u8)(value & 0xFF); ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x3C, data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_ts_buf_clear(struct cxd2880_tnrdmd *tnr_dmd, ++ u8 clear_overflow_flag, ++ u8 clear_underflow_flag, ++ u8 clear_buf) ++{ ++ u8 data[2] = { 0 }; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) && ++ (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ data[0] = (u8)(clear_overflow_flag ? 0x02 : 0x00); ++ data[0] |= (u8)(clear_underflow_flag ? 0x01 : 0x00); ++ data[1] = (u8)(clear_buf ? 0x01 : 0x00); ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x9F, data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_chip_id(struct cxd2880_tnrdmd *tnr_dmd, ++ enum cxd2880_tnrdmd_chip_id *chip_id) ++{ ++ u8 data = 0; ++ ++ if ((!tnr_dmd) || (!chip_id)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0xFD, &data, ++ 1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ *chip_id = (enum cxd2880_tnrdmd_chip_id)data; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_set_and_save_reg_bits(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum cxd2880_io_tgt tgt, ++ u8 bank, u8 address, ++ u8 value, u8 bit_mask) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) && ++ (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ tgt, 0x00, bank) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (cxd2880_io_set_reg_bits(tnr_dmd->io, tgt, address, value, bit_mask) ++ != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ ret = set_cfg_mem(tnr_dmd, tgt, bank, address, value, bit_mask); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_set_scan_mode(struct cxd2880_tnrdmd *tnr_dmd, ++ enum cxd2880_dtv_sys sys, ++ u8 scan_mode_end) ++{ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) && ++ (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ CXD2880_ARG_UNUSED(sys); ++ ++ tnr_dmd->scan_mode = scan_mode_end; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ ret = ++ cxd2880_tnrdmd_set_scan_mode(tnr_dmd->diver_sub, sys, ++ scan_mode_end); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_set_pid_ftr(struct cxd2880_tnrdmd *tnr_dmd, ++ struct cxd2880_tnrdmd_pid_ftr_cfg ++ *pid_ftr_cfg) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) && ++ (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->create_param.ts_output_if == CXD2880_TNRDMD_TSOUT_IF_TS) ++ return CXD2880_RESULT_ERROR_NOSUPPORT; ++ ++ if (pid_ftr_cfg) { ++ tnr_dmd->pid_ftr_cfg = *pid_ftr_cfg; ++ tnr_dmd->pid_ftr_cfg_en = 1; ++ } else { ++ tnr_dmd->pid_ftr_cfg_en = 0; ++ } ++ ++ if (tnr_dmd->state == CXD2880_TNRDMD_STATE_ACTIVE) { ++ ret = pid_ftr_setting(tnr_dmd, pid_ftr_cfg); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_set_rf_lvl_cmpstn(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum ++ cxd2880_ret(*rf_lvl_cmpstn) ++ (struct cxd2880_tnrdmd *, ++ int *)) ++{ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ tnr_dmd->rf_lvl_cmpstn = rf_lvl_cmpstn; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_set_rf_lvl_cmpstn_sub(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum ++ cxd2880_ret ++ (*rf_lvl_cmpstn)(struct ++ cxd2880_tnrdmd ++ *, ++ int *)) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ ret = ++ cxd2880_tnrdmd_set_rf_lvl_cmpstn(tnr_dmd->diver_sub, rf_lvl_cmpstn); ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_set_lna_thrs(struct cxd2880_tnrdmd *tnr_dmd, ++ struct ++ cxd2880_tnrdmd_lna_thrs_tbl_air ++ *tbl_air, ++ struct ++ cxd2880_tnrdmd_lna_thrs_tbl_cable ++ *tbl_cable) ++{ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ tnr_dmd->lna_thrs_tbl_air = tbl_air; ++ tnr_dmd->lna_thrs_tbl_cable = tbl_cable; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_set_lna_thrs_sub(struct cxd2880_tnrdmd *tnr_dmd, ++ struct ++ cxd2880_tnrdmd_lna_thrs_tbl_air ++ *tbl_air, ++ struct ++ cxd2880_tnrdmd_lna_thrs_tbl_cable ++ *tbl_cable) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ ret = ++ cxd2880_tnrdmd_set_lna_thrs(tnr_dmd->diver_sub, tbl_air, tbl_cable); ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_set_ts_pin_high_low(struct cxd2880_tnrdmd ++ *tnr_dmd, u8 en, u8 value) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->create_param.ts_output_if != CXD2880_TNRDMD_TSOUT_IF_TS) ++ return CXD2880_RESULT_ERROR_NOSUPPORT; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (en) { ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x50, ++ ((value & 0x1F) | 0x80)) != ++ CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x52, ++ (value & 0x1F)) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } else { ++ ret = tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x50, 0x3F); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x52, ++ 0x1F) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ ret = load_cfg_mem(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_set_ts_output(struct cxd2880_tnrdmd *tnr_dmd, ++ u8 en) ++{ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) && ++ (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ switch (tnr_dmd->create_param.ts_output_if) { ++ case CXD2880_TNRDMD_TSOUT_IF_TS: ++ if (en) { ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x52, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xC3, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } else { ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xC3, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x52, ++ 0x1F) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ break; ++ ++ case CXD2880_TNRDMD_TSOUT_IF_SPI: ++ break; ++ ++ case CXD2880_TNRDMD_TSOUT_IF_SDIO: ++ break; ++ ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret slvt_freeze_reg(struct cxd2880_tnrdmd *tnr_dmd) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ switch (tnr_dmd->create_param.ts_output_if) { ++ case CXD2880_TNRDMD_TSOUT_IF_SPI: ++ case CXD2880_TNRDMD_TSOUT_IF_SDIO: ++ { ++ u8 data = 0; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ &data, ++ 1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ break; ++ case CXD2880_TNRDMD_TSOUT_IF_TS: ++ default: ++ break; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x01, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ return ret; ++} +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd.h b/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd.h +new file mode 100644 +index 0000000000000000000000000000000000000000..26e29b3b9f6bdba32a181595e8298cda3325112c +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd.h +@@ -0,0 +1,395 @@ ++/* ++ * cxd2880_tnrdmd.h ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * common control interface ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#ifndef CXD2880_TNRDMD_H ++#define CXD2880_TNRDMD_H ++ ++#include "cxd2880_common.h" ++#include "cxd2880_io.h" ++#include "cxd2880_dtv.h" ++#include "cxd2880_dvbt.h" ++#include "cxd2880_dvbt2.h" ++ ++#define CXD2880_TNRDMD_MAX_CFG_MEM_COUNT 100 ++ ++#define slvt_unfreeze_reg(tnr_dmd) ((void)((tnr_dmd)->io->write_reg\ ++((tnr_dmd)->io, CXD2880_IO_TGT_DMD, 0x01, 0x00))) ++ ++#define CXD2880_TNRDMD_INTERRUPT_TYPE_BUF_UNDERFLOW 0x0001 ++#define CXD2880_TNRDMD_INTERRUPT_TYPE_BUF_OVERFLOW 0x0002 ++#define CXD2880_TNRDMD_INTERRUPT_TYPE_BUF_ALMOST_EMPTY 0x0004 ++#define CXD2880_TNRDMD_INTERRUPT_TYPE_BUF_ALMOST_FULL 0x0008 ++#define CXD2880_TNRDMD_INTERRUPT_TYPE_BUF_RRDY 0x0010 ++#define CXD2880_TNRDMD_INTERRUPT_TYPE_ILLEGAL_COMMAND 0x0020 ++#define CXD2880_TNRDMD_INTERRUPT_TYPE_ILLEGAL_ACCESS 0x0040 ++#define CXD2880_TNRDMD_INTERRUPT_TYPE_CPU_ERROR 0x0100 ++#define CXD2880_TNRDMD_INTERRUPT_TYPE_LOCK 0x0200 ++#define CXD2880_TNRDMD_INTERRUPT_TYPE_INV_LOCK 0x0400 ++#define CXD2880_TNRDMD_INTERRUPT_TYPE_NOOFDM 0x0800 ++#define CXD2880_TNRDMD_INTERRUPT_TYPE_EWS 0x1000 ++#define CXD2880_TNRDMD_INTERRUPT_TYPE_EEW 0x2000 ++#define CXD2880_TNRDMD_INTERRUPT_TYPE_FEC_FAIL 0x4000 ++ ++#define CXD2880_TNRDMD_INTERRUPT_LOCK_SEL_L1POST_OK 0x01 ++#define CXD2880_TNRDMD_INTERRUPT_LOCK_SEL_DMD_LOCK 0x02 ++#define CXD2880_TNRDMD_INTERRUPT_LOCK_SEL_TS_LOCK 0x04 ++ ++enum cxd2880_tnrdmd_chip_id { ++ CXD2880_TNRDMD_CHIP_ID_UNKNOWN = 0x00, ++ CXD2880_TNRDMD_CHIP_ID_CXD2880_ES1_0X = 0x62, ++ CXD2880_TNRDMD_CHIP_ID_CXD2880_ES1_11 = 0x6A ++}; ++ ++#define CXD2880_TNRDMD_CHIP_ID_VALID(chip_id) (((chip_id) == \ ++CXD2880_TNRDMD_CHIP_ID_CXD2880_ES1_0X) || \ ++((chip_id) == CXD2880_TNRDMD_CHIP_ID_CXD2880_ES1_11)) ++ ++enum cxd2880_tnrdmd_state { ++ CXD2880_TNRDMD_STATE_UNKNOWN, ++ CXD2880_TNRDMD_STATE_SLEEP, ++ CXD2880_TNRDMD_STATE_ACTIVE, ++ CXD2880_TNRDMD_STATE_INVALID ++}; ++ ++enum cxd2880_tnrdmd_divermode { ++ CXD2880_TNRDMD_DIVERMODE_SINGLE, ++ CXD2880_TNRDMD_DIVERMODE_MAIN, ++ CXD2880_TNRDMD_DIVERMODE_SUB ++}; ++ ++enum cxd2880_tnrdmd_clockmode { ++ CXD2880_TNRDMD_CLOCKMODE_UNKNOWN, ++ CXD2880_TNRDMD_CLOCKMODE_A, ++ CXD2880_TNRDMD_CLOCKMODE_B, ++ CXD2880_TNRDMD_CLOCKMODE_C ++}; ++ ++enum cxd2880_tnrdmd_tsout_if { ++ CXD2880_TNRDMD_TSOUT_IF_TS, ++ CXD2880_TNRDMD_TSOUT_IF_SPI, ++ CXD2880_TNRDMD_TSOUT_IF_SDIO ++}; ++ ++enum cxd2880_tnrdmd_xtal_share { ++ CXD2880_TNRDMD_XTAL_SHARE_NONE, ++ CXD2880_TNRDMD_XTAL_SHARE_EXTREF, ++ CXD2880_TNRDMD_XTAL_SHARE_MASTER, ++ CXD2880_TNRDMD_XTAL_SHARE_SLAVE ++}; ++ ++enum cxd2880_tnrdmd_spectrum_sense { ++ CXD2880_TNRDMD_SPECTRUM_NORMAL, ++ CXD2880_TNRDMD_SPECTRUM_INV ++}; ++ ++enum cxd2880_tnrdmd_cfg_id { ++ CXD2880_TNRDMD_CFG_OUTPUT_SEL_MSB, ++ CXD2880_TNRDMD_CFG_TSVALID_ACTIVE_HI, ++ CXD2880_TNRDMD_CFG_TSSYNC_ACTIVE_HI, ++ CXD2880_TNRDMD_CFG_TSERR_ACTIVE_HI, ++ CXD2880_TNRDMD_CFG_LATCH_ON_POSEDGE, ++ CXD2880_TNRDMD_CFG_TSCLK_CONT, ++ CXD2880_TNRDMD_CFG_TSCLK_MASK, ++ CXD2880_TNRDMD_CFG_TSVALID_MASK, ++ CXD2880_TNRDMD_CFG_TSERR_MASK, ++ CXD2880_TNRDMD_CFG_TSERR_VALID_DIS, ++ CXD2880_TNRDMD_CFG_TSPIN_CURRENT, ++ CXD2880_TNRDMD_CFG_TSPIN_PULLUP_MANUAL, ++ CXD2880_TNRDMD_CFG_TSPIN_PULLUP, ++ CXD2880_TNRDMD_CFG_TSCLK_FREQ, ++ CXD2880_TNRDMD_CFG_TSBYTECLK_MANUAL, ++ CXD2880_TNRDMD_CFG_TS_PACKET_GAP, ++ CXD2880_TNRDMD_CFG_TS_BACKWARDS_COMPATIBLE, ++ CXD2880_TNRDMD_CFG_PWM_VALUE, ++ CXD2880_TNRDMD_CFG_INTERRUPT, ++ CXD2880_TNRDMD_CFG_INTERRUPT_LOCK_SEL, ++ CXD2880_TNRDMD_CFG_INTERRUPT_INV_LOCK_SEL, ++ CXD2880_TNRDMD_CFG_TS_BUF_ALMOST_EMPTY_THRS, ++ CXD2880_TNRDMD_CFG_TS_BUF_ALMOST_FULL_THRS, ++ CXD2880_TNRDMD_CFG_TS_BUF_RRDY_THRS, ++ CXD2880_TNRDMD_CFG_FIXED_CLOCKMODE, ++ CXD2880_TNRDMD_CFG_CABLE_INPUT, ++ CXD2880_TNRDMD_CFG_DVBT2_FEF_INTERMITTENT_BASE, ++ CXD2880_TNRDMD_CFG_DVBT2_FEF_INTERMITTENT_LITE, ++ CXD2880_TNRDMD_CFG_BLINDTUNE_DVBT2_FIRST, ++ CXD2880_TNRDMD_CFG_DVBT_BERN_PERIOD, ++ CXD2880_TNRDMD_CFG_DVBT_VBER_PERIOD, ++ CXD2880_TNRDMD_CFG_DVBT_PER_MES, ++ CXD2880_TNRDMD_CFG_DVBT2_BBER_MES, ++ CXD2880_TNRDMD_CFG_DVBT2_LBER_MES, ++ CXD2880_TNRDMD_CFG_DVBT2_PER_MES, ++ CXD2880_TNRDMD_CFG_ISDBT_BERPER_PERIOD ++}; ++ ++enum cxd2880_tnrdmd_lock_result { ++ CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT, ++ CXD2880_TNRDMD_LOCK_RESULT_LOCKED, ++ CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED ++}; ++ ++enum cxd2880_tnrdmd_gpio_mode { ++ CXD2880_TNRDMD_GPIO_MODE_OUTPUT = 0x00, ++ CXD2880_TNRDMD_GPIO_MODE_INPUT = 0x01, ++ CXD2880_TNRDMD_GPIO_MODE_INT = 0x02, ++ CXD2880_TNRDMD_GPIO_MODE_FEC_FAIL = 0x03, ++ CXD2880_TNRDMD_GPIO_MODE_PWM = 0x04, ++ CXD2880_TNRDMD_GPIO_MODE_EWS = 0x05, ++ CXD2880_TNRDMD_GPIO_MODE_EEW = 0x06 ++}; ++ ++enum cxd2880_tnrdmd_serial_ts_clk { ++ CXD2880_TNRDMD_SERIAL_TS_CLK_FULL, ++ CXD2880_TNRDMD_SERIAL_TS_CLK_HALF ++}; ++ ++struct cxd2880_tnrdmd_cfg_mem { ++ enum cxd2880_io_tgt tgt; ++ u8 bank; ++ u8 address; ++ u8 value; ++ u8 bit_mask; ++}; ++ ++struct cxd2880_tnrdmd_pid_cfg { ++ u8 is_en; ++ u16 pid; ++}; ++ ++struct cxd2880_tnrdmd_pid_ftr_cfg { ++ u8 is_negative; ++ struct cxd2880_tnrdmd_pid_cfg pid_cfg[32]; ++}; ++ ++struct cxd2880_tnrdmd_ts_buf_info { ++ u8 read_ready; ++ u8 almost_full; ++ u8 almost_empty; ++ u8 overflow; ++ u8 underflow; ++ u16 packet_num; ++}; ++ ++struct cxd2880_tnrdmd_lna_thrs { ++ u8 off_on; ++ u8 on_off; ++}; ++ ++struct cxd2880_tnrdmd_lna_thrs_tbl_air { ++ struct cxd2880_tnrdmd_lna_thrs thrs[24]; ++}; ++ ++struct cxd2880_tnrdmd_lna_thrs_tbl_cable { ++ struct cxd2880_tnrdmd_lna_thrs thrs[32]; ++}; ++ ++struct cxd2880_tnrdmd_create_param { ++ enum cxd2880_tnrdmd_tsout_if ts_output_if; ++ u8 en_internal_ldo; ++ enum cxd2880_tnrdmd_xtal_share xtal_share_type; ++ u8 xosc_cap; ++ u8 xosc_i; ++ u8 is_cxd2881gg; ++ u8 stationary_use; ++}; ++ ++struct cxd2880_tnrdmd_diver_create_param { ++ enum cxd2880_tnrdmd_tsout_if ts_output_if; ++ u8 en_internal_ldo; ++ u8 xosc_cap_main; ++ u8 xosc_i_main; ++ u8 xosc_i_sub; ++ u8 is_cxd2881gg; ++ u8 stationary_use; ++}; ++ ++struct cxd2880_tnrdmd { ++ struct cxd2880_tnrdmd *diver_sub; ++ struct cxd2880_io *io; ++ struct cxd2880_tnrdmd_create_param create_param; ++ enum cxd2880_tnrdmd_divermode diver_mode; ++ enum cxd2880_tnrdmd_clockmode fixed_clk_mode; ++ u8 is_cable_input; ++ u8 en_fef_intmtnt_base; ++ u8 en_fef_intmtnt_lite; ++ u8 blind_tune_dvbt2_first; ++ enum cxd2880_ret (*rf_lvl_cmpstn)(struct cxd2880_tnrdmd *tnr_dmd, ++ int *rf_lvl_db); ++ struct cxd2880_tnrdmd_lna_thrs_tbl_air *lna_thrs_tbl_air; ++ struct cxd2880_tnrdmd_lna_thrs_tbl_cable *lna_thrs_tbl_cable; ++ u8 srl_ts_clk_mod_cnts; ++ enum cxd2880_tnrdmd_serial_ts_clk srl_ts_clk_frq; ++ u8 ts_byte_clk_manual_setting; ++ u8 is_ts_backwards_compatible_mode; ++ struct cxd2880_tnrdmd_cfg_mem cfg_mem[CXD2880_TNRDMD_MAX_CFG_MEM_COUNT]; ++ u8 cfg_mem_last_entry; ++ struct cxd2880_tnrdmd_pid_ftr_cfg pid_ftr_cfg; ++ u8 pid_ftr_cfg_en; ++ void *user; ++ enum cxd2880_tnrdmd_chip_id chip_id; ++ enum cxd2880_tnrdmd_state state; ++ enum cxd2880_tnrdmd_clockmode clk_mode; ++ u32 frequency_khz; ++ enum cxd2880_dtv_sys sys; ++ enum cxd2880_dtv_bandwidth bandwidth; ++ u8 scan_mode; ++ struct cxd2880_atomic cancel; ++}; ++ ++enum cxd2880_ret cxd2880_tnrdmd_create(struct cxd2880_tnrdmd *tnr_dmd, ++ struct cxd2880_io *io, ++ struct cxd2880_tnrdmd_create_param ++ *create_param); ++ ++enum cxd2880_ret cxd2880_tnrdmd_diver_create(struct cxd2880_tnrdmd ++ *tnr_dmd_main, ++ struct cxd2880_io *io_main, ++ struct cxd2880_tnrdmd *tnr_dmd_sub, ++ struct cxd2880_io *io_sub, ++ struct ++ cxd2880_tnrdmd_diver_create_param ++ *create_param); ++ ++enum cxd2880_ret cxd2880_tnrdmd_init1(struct cxd2880_tnrdmd *tnr_dmd); ++ ++enum cxd2880_ret cxd2880_tnrdmd_init2(struct cxd2880_tnrdmd *tnr_dmd); ++ ++enum cxd2880_ret cxd2880_tnrdmd_check_internal_cpu_status(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ u8 *task_completed); ++ ++enum cxd2880_ret cxd2880_tnrdmd_common_tune_setting1(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum cxd2880_dtv_sys sys, ++ u32 frequency_khz, ++ enum cxd2880_dtv_bandwidth ++ bandwidth, u8 one_seg_opt, ++ u8 one_seg_opt_shft_dir); ++ ++enum cxd2880_ret cxd2880_tnrdmd_common_tune_setting2(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum cxd2880_dtv_sys sys, ++ u8 en_fef_intmtnt_ctrl); ++ ++enum cxd2880_ret cxd2880_tnrdmd_sleep(struct cxd2880_tnrdmd *tnr_dmd); ++ ++enum cxd2880_ret cxd2880_tnrdmd_set_cfg(struct cxd2880_tnrdmd *tnr_dmd, ++ enum cxd2880_tnrdmd_cfg_id id, ++ int value); ++ ++enum cxd2880_ret cxd2880_tnrdmd_gpio_set_cfg(struct cxd2880_tnrdmd *tnr_dmd, ++ u8 id, ++ u8 en, ++ enum cxd2880_tnrdmd_gpio_mode mode, ++ u8 open_drain, u8 invert); ++ ++enum cxd2880_ret cxd2880_tnrdmd_gpio_set_cfg_sub(struct cxd2880_tnrdmd *tnr_dmd, ++ u8 id, ++ u8 en, ++ enum cxd2880_tnrdmd_gpio_mode ++ mode, u8 open_drain, ++ u8 invert); ++ ++enum cxd2880_ret cxd2880_tnrdmd_gpio_read(struct cxd2880_tnrdmd *tnr_dmd, ++ u8 id, u8 *value); ++ ++enum cxd2880_ret cxd2880_tnrdmd_gpio_read_sub(struct cxd2880_tnrdmd *tnr_dmd, ++ u8 id, u8 *value); ++ ++enum cxd2880_ret cxd2880_tnrdmd_gpio_write(struct cxd2880_tnrdmd *tnr_dmd, ++ u8 id, u8 value); ++ ++enum cxd2880_ret cxd2880_tnrdmd_gpio_write_sub(struct cxd2880_tnrdmd *tnr_dmd, ++ u8 id, u8 value); ++ ++enum cxd2880_ret cxd2880_tnrdmd_interrupt_read(struct cxd2880_tnrdmd *tnr_dmd, ++ u16 *value); ++ ++enum cxd2880_ret cxd2880_tnrdmd_interrupt_clear(struct cxd2880_tnrdmd *tnr_dmd, ++ u16 value); ++ ++enum cxd2880_ret cxd2880_tnrdmd_ts_buf_clear(struct cxd2880_tnrdmd *tnr_dmd, ++ u8 clear_overflow_flag, ++ u8 clear_underflow_flag, ++ u8 clear_buf); ++ ++enum cxd2880_ret cxd2880_tnrdmd_chip_id(struct cxd2880_tnrdmd *tnr_dmd, ++ enum cxd2880_tnrdmd_chip_id *chip_id); ++ ++enum cxd2880_ret cxd2880_tnrdmd_set_and_save_reg_bits(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum cxd2880_io_tgt tgt, ++ u8 bank, u8 address, ++ u8 value, u8 bit_mask); ++ ++enum cxd2880_ret cxd2880_tnrdmd_set_scan_mode(struct cxd2880_tnrdmd *tnr_dmd, ++ enum cxd2880_dtv_sys sys, ++ u8 scan_mode_end); ++ ++enum cxd2880_ret cxd2880_tnrdmd_set_pid_ftr(struct cxd2880_tnrdmd *tnr_dmd, ++ struct cxd2880_tnrdmd_pid_ftr_cfg ++ *pid_ftr_cfg); ++ ++enum cxd2880_ret cxd2880_tnrdmd_set_rf_lvl_cmpstn(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum ++ cxd2880_ret(*rf_lvl_cmpstn) ++ (struct cxd2880_tnrdmd *, ++ int *)); ++ ++enum cxd2880_ret cxd2880_tnrdmd_set_rf_lvl_cmpstn_sub(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum ++ cxd2880_ret ++ (*rf_lvl_cmpstn)(struct ++ cxd2880_tnrdmd ++ *, ++ int *)); ++ ++enum cxd2880_ret cxd2880_tnrdmd_set_lna_thrs(struct cxd2880_tnrdmd *tnr_dmd, ++ struct ++ cxd2880_tnrdmd_lna_thrs_tbl_air ++ *tbl_air, ++ struct ++ cxd2880_tnrdmd_lna_thrs_tbl_cable ++ *tbl_cable); ++ ++enum cxd2880_ret cxd2880_tnrdmd_set_lna_thrs_sub(struct cxd2880_tnrdmd *tnr_dmd, ++ struct ++ cxd2880_tnrdmd_lna_thrs_tbl_air ++ *tbl_air, ++ struct ++ cxd2880_tnrdmd_lna_thrs_tbl_cable ++ *tbl_cable); ++ ++enum cxd2880_ret cxd2880_tnrdmd_set_ts_pin_high_low(struct cxd2880_tnrdmd ++ *tnr_dmd, u8 en, u8 value); ++ ++enum cxd2880_ret cxd2880_tnrdmd_set_ts_output(struct cxd2880_tnrdmd *tnr_dmd, ++ u8 en); ++ ++enum cxd2880_ret slvt_freeze_reg(struct cxd2880_tnrdmd *tnr_dmd); ++ ++#endif +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_driver_version.h b/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_driver_version.h +new file mode 100644 +index 0000000000000000000000000000000000000000..68fb3af04bd41719d407f333314635622cd982b0 +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_driver_version.h +@@ -0,0 +1,29 @@ ++/* ++ * cxd2880_tnrdmd_driver_version.h ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * version information ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#define CXD2880_TNRDMD_DRIVER_VERSION "1.4.1 - 1.0.1" ++ ++#define CXD2880_TNRDMD_DRIVER_RELEASE_DATE "2017-04-13" +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt.c b/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt.c +new file mode 100644 +index 0000000000000000000000000000000000000000..f36cf533ec1795bf033531b0a347b60d917fe35f +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt.c +@@ -0,0 +1,1072 @@ ++/* ++ * cxd2880_tnrdmd_dvbt.c ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * control functions for DVB-T ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#include "cxd2880_tnrdmd_dvbt.h" ++#include "cxd2880_tnrdmd_dvbt_mon.h" ++ ++static enum cxd2880_ret x_tune_dvbt_demod_setting(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum cxd2880_dtv_bandwidth ++ bandwidth, ++ enum cxd2880_tnrdmd_clockmode ++ clk_mode) ++{ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x31, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ { ++ u8 data_a[2] = { 0x52, 0x49 }; ++ u8 data_b[2] = { 0x5D, 0x55 }; ++ u8 data_c[2] = { 0x60, 0x00 }; ++ u8 *data = NULL; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x04) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ data = data_a; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = data_b; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = data_c; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x65, data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x5D, ++ 0x07) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_SUB) { ++ u8 data[2] = { 0x01, 0x01 }; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xCE, data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x04) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x5C, ++ 0xFB) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x10) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xA4, ++ 0x03) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x14) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xB0, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x25) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ { ++ u8 data[2] = { 0x01, 0xF0 }; ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xF0, data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if ((tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) || ++ (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)) { ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x12) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x44, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) { ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x11) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x87, ++ 0xD2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_SUB) { ++ u8 data_a[3] = { 0x73, 0xCA, 0x49 }; ++ u8 data_b[3] = { 0xC8, 0x13, 0xAA }; ++ u8 data_c[3] = { 0xDC, 0x6C, 0x00 }; ++ u8 *data = NULL; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x04) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ data = data_a; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = data_b; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = data_c; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x68, data, ++ 3) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x04) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ switch (bandwidth) { ++ case CXD2880_DTV_BW_8_MHZ: ++ ++ { ++ u8 data_ac[5] = { 0x15, 0x00, 0x00, 0x00, ++ 0x00 ++ }; ++ u8 data_b[5] = { 0x14, 0x6A, 0xAA, 0xAA, ++ 0xAA ++ }; ++ u8 *data = NULL; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = data_ac; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = data_b; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x60, ++ data, ++ 5) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x4A, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ { ++ u8 data_a[2] = { 0x01, 0x28 }; ++ u8 data_b[2] = { 0x11, 0x44 }; ++ u8 data_c[2] = { 0x15, 0x28 }; ++ u8 *data = NULL; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ data = data_a; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = data_b; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = data_c; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x7D, ++ data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ { ++ u8 data = 0; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = 0x35; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = 0x34; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x71, ++ data) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ u8 data_a[5] = { 0x30, 0x00, 0x00, 0x90, ++ 0x00 ++ }; ++ u8 data_b[5] = { 0x36, 0x71, 0x00, 0xA3, ++ 0x55 ++ }; ++ u8 data_c[5] = { 0x38, 0x00, 0x00, 0xA8, ++ 0x00 ++ }; ++ u8 *data = NULL; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ data = data_a; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = data_b; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = data_c; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x4B, ++ &data[0], ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x51, ++ &data[2], ++ 3) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ { ++ u8 data[4] = { 0xB3, 0x00, 0x01, 0x02 }; ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x72, ++ &data[0], ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x6B, ++ &data[2], ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ break; ++ ++ case CXD2880_DTV_BW_7_MHZ: ++ ++ { ++ u8 data_ac[5] = { 0x18, 0x00, 0x00, 0x00, ++ 0x00 ++ }; ++ u8 data_b[5] = { 0x17, 0x55, 0x55, 0x55, ++ 0x55 ++ }; ++ u8 *data = NULL; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = data_ac; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = data_b; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x60, ++ data, ++ 5) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x4A, ++ 0x02) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ { ++ u8 data_a[2] = { 0x12, 0x4C }; ++ u8 data_b[2] = { 0x1F, 0x15 }; ++ u8 data_c[2] = { 0x1F, 0xF8 }; ++ u8 *data = NULL; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ data = data_a; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = data_b; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = data_c; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x7D, ++ data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ { ++ u8 data = 0; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = 0x2F; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = 0x2E; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x71, ++ data) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ u8 data_a[5] = { 0x36, 0xDB, 0x00, 0xA4, ++ 0x92 ++ }; ++ u8 data_b[5] = { 0x3E, 0x38, 0x00, 0xBA, ++ 0xAA ++ }; ++ u8 data_c[5] = { 0x40, 0x00, 0x00, 0xC0, ++ 0x00 ++ }; ++ u8 *data = NULL; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ data = data_a; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = data_b; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = data_c; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x4B, ++ &data[0], ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x51, ++ &data[2], ++ 3) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ { ++ u8 data[4] = { 0xB8, 0x00, 0x00, 0x03 }; ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x72, ++ &data[0], ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x6B, ++ &data[2], ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ break; ++ ++ case CXD2880_DTV_BW_6_MHZ: ++ ++ { ++ u8 data_ac[5] = { 0x1C, 0x00, 0x00, 0x00, ++ 0x00 ++ }; ++ u8 data_b[5] = { 0x1B, 0x38, 0xE3, 0x8E, ++ 0x38 ++ }; ++ u8 *data = NULL; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = data_ac; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = data_b; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x60, ++ data, ++ 5) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x4A, ++ 0x04) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ { ++ u8 data_a[2] = { 0x1F, 0xF8 }; ++ u8 data_b[2] = { 0x24, 0x43 }; ++ u8 data_c[2] = { 0x25, 0x4C }; ++ u8 *data = NULL; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ data = data_a; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = data_b; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = data_c; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x7D, ++ data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ { ++ u8 data = 0; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = 0x29; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = 0x2A; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x71, ++ data) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ u8 data_a[5] = { 0x40, 0x00, 0x00, 0xC0, ++ 0x00 ++ }; ++ u8 data_b[5] = { 0x48, 0x97, 0x00, 0xD9, ++ 0xC7 ++ }; ++ u8 data_c[5] = { 0x4A, 0xAA, 0x00, 0xDF, ++ 0xFF ++ }; ++ u8 *data = NULL; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ data = data_a; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = data_b; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = data_c; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x4B, ++ &data[0], ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x51, ++ &data[2], ++ 3) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ { ++ u8 data[4] = { 0xBE, 0xAB, 0x00, 0x03 }; ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x72, ++ &data[0], ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x6B, ++ &data[2], ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ break; ++ ++ case CXD2880_DTV_BW_5_MHZ: ++ ++ { ++ u8 data_ac[5] = { 0x21, 0x99, 0x99, 0x99, ++ 0x99 ++ }; ++ u8 data_b[5] = { 0x20, 0xAA, 0xAA, 0xAA, ++ 0xAA ++ }; ++ u8 *data = NULL; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = data_ac; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = data_b; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x60, ++ data, ++ 5) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x4A, ++ 0x06) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ { ++ u8 data_a[2] = { 0x26, 0x5D }; ++ u8 data_b[2] = { 0x2B, 0x84 }; ++ u8 data_c[2] = { 0x2C, 0xC2 }; ++ u8 *data = NULL; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ data = data_a; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = data_b; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = data_c; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x7D, ++ data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ { ++ u8 data = 0; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = 0x24; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = 0x23; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x71, ++ data) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ u8 data_a[5] = { 0x4C, 0xCC, 0x00, 0xE6, ++ 0x66 ++ }; ++ u8 data_b[5] = { 0x57, 0x1C, 0x01, 0x05, ++ 0x55 ++ }; ++ u8 data_c[5] = { 0x59, 0x99, 0x01, 0x0C, ++ 0xCC ++ }; ++ u8 *data = NULL; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ data = data_a; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = data_b; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = data_c; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x4B, ++ &data[0], ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x51, ++ &data[2], ++ 3) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ { ++ u8 data[4] = { 0xC8, 0x01, 0x00, 0x03 }; ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x72, ++ &data[0], ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x6B, ++ &data[2], ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ break; ++ ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xFD, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++static enum cxd2880_ret x_sleep_dvbt_demod_setting(struct cxd2880_tnrdmd ++ *tnr_dmd) ++{ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x04) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x5C, ++ 0xD8) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x10) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xA4, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) { ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x11) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x87, ++ 0x04) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ return CXD2880_RESULT_OK; ++} ++ ++static enum cxd2880_ret dvbt_set_profile(struct cxd2880_tnrdmd *tnr_dmd, ++ enum cxd2880_dvbt_profile profile) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x10) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x67, ++ (profile == ++ CXD2880_DVBT_PROFILE_HP) ? 0x00 : 0x01) != ++ CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_tune1(struct cxd2880_tnrdmd *tnr_dmd, ++ struct cxd2880_dvbt_tune_param ++ *tune_param) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!tune_param)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) && ++ (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = ++ cxd2880_tnrdmd_common_tune_setting1(tnr_dmd, CXD2880_DTV_SYS_DVBT, ++ tune_param->center_freq_khz, ++ tune_param->bandwidth, 0, 0); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ ret = ++ x_tune_dvbt_demod_setting(tnr_dmd, tune_param->bandwidth, ++ tnr_dmd->clk_mode); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ ret = ++ x_tune_dvbt_demod_setting(tnr_dmd->diver_sub, ++ tune_param->bandwidth, ++ tnr_dmd->diver_sub->clk_mode); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ ret = dvbt_set_profile(tnr_dmd, tune_param->profile); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_tune2(struct cxd2880_tnrdmd *tnr_dmd, ++ struct cxd2880_dvbt_tune_param ++ *tune_param) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!tune_param)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) && ++ (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = ++ cxd2880_tnrdmd_common_tune_setting2(tnr_dmd, CXD2880_DTV_SYS_DVBT, ++ 0); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ tnr_dmd->state = CXD2880_TNRDMD_STATE_ACTIVE; ++ tnr_dmd->frequency_khz = tune_param->center_freq_khz; ++ tnr_dmd->sys = CXD2880_DTV_SYS_DVBT; ++ tnr_dmd->bandwidth = tune_param->bandwidth; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ tnr_dmd->diver_sub->state = CXD2880_TNRDMD_STATE_ACTIVE; ++ tnr_dmd->diver_sub->frequency_khz = tune_param->center_freq_khz; ++ tnr_dmd->diver_sub->sys = CXD2880_DTV_SYS_DVBT; ++ tnr_dmd->diver_sub->bandwidth = tune_param->bandwidth; ++ } ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_sleep_setting(struct cxd2880_tnrdmd ++ *tnr_dmd) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) && ++ (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = x_sleep_dvbt_demod_setting(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ ret = x_sleep_dvbt_demod_setting(tnr_dmd->diver_sub); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_check_demod_lock(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum ++ cxd2880_tnrdmd_lock_result ++ *lock) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ u8 sync_stat = 0; ++ u8 ts_lock = 0; ++ u8 unlock_detected = 0; ++ u8 unlock_detected_sub = 0; ++ ++ if ((!tnr_dmd) || (!lock)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = ++ cxd2880_tnrdmd_dvbt_mon_sync_stat(tnr_dmd, &sync_stat, &ts_lock, ++ &unlock_detected); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE) { ++ if (sync_stat == 6) ++ *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED; ++ else if (unlock_detected) ++ *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED; ++ else ++ *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT; ++ ++ return ret; ++ } ++ ++ if (sync_stat == 6) { ++ *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED; ++ return ret; ++ } ++ ++ ret = ++ cxd2880_tnrdmd_dvbt_mon_sync_stat_sub(tnr_dmd, &sync_stat, ++ &unlock_detected_sub); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (sync_stat == 6) ++ *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED; ++ else if (unlock_detected && unlock_detected_sub) ++ *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED; ++ else ++ *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT; ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_check_ts_lock(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum ++ cxd2880_tnrdmd_lock_result ++ *lock) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ u8 sync_stat = 0; ++ u8 ts_lock = 0; ++ u8 unlock_detected = 0; ++ u8 unlock_detected_sub = 0; ++ ++ if ((!tnr_dmd) || (!lock)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = ++ cxd2880_tnrdmd_dvbt_mon_sync_stat(tnr_dmd, &sync_stat, &ts_lock, ++ &unlock_detected); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE) { ++ if (ts_lock) ++ *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED; ++ else if (unlock_detected) ++ *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED; ++ else ++ *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT; ++ ++ return ret; ++ } ++ ++ if (ts_lock) { ++ *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED; ++ return ret; ++ } else if (!unlock_detected) { ++ *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT; ++ return ret; ++ } ++ ++ ret = ++ cxd2880_tnrdmd_dvbt_mon_sync_stat_sub(tnr_dmd, &sync_stat, ++ &unlock_detected_sub); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (unlock_detected && unlock_detected_sub) ++ *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED; ++ else ++ *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT; ++ ++ return ret; ++} +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt.h b/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt.h +new file mode 100644 +index 0000000000000000000000000000000000000000..de394d8e27f323a9ccfacbe3e56a3d6f40b6babe +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt.h +@@ -0,0 +1,62 @@ ++/* ++ * cxd2880_tnrdmd_dvbt.h ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * control interface for DVB-T ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#ifndef CXD2880_TNRDMD_DVBT_H ++#define CXD2880_TNRDMD_DVBT_H ++ ++#include "cxd2880_common.h" ++#include "cxd2880_tnrdmd.h" ++ ++struct cxd2880_dvbt_tune_param { ++ u32 center_freq_khz; ++ enum cxd2880_dtv_bandwidth bandwidth; ++ enum cxd2880_dvbt_profile profile; ++}; ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_tune1(struct cxd2880_tnrdmd *tnr_dmd, ++ struct cxd2880_dvbt_tune_param ++ *tune_param); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_tune2(struct cxd2880_tnrdmd *tnr_dmd, ++ struct cxd2880_dvbt_tune_param ++ *tune_param); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_sleep_setting(struct cxd2880_tnrdmd ++ *tnr_dmd); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_check_demod_lock(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum ++ cxd2880_tnrdmd_lock_result ++ *lock); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_check_ts_lock(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum ++ cxd2880_tnrdmd_lock_result ++ *lock); ++ ++#endif +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt2.c b/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt2.c +new file mode 100644 +index 0000000000000000000000000000000000000000..bdad65b7298ab0ad131a6e6579e304fb279359a5 +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt2.c +@@ -0,0 +1,1309 @@ ++/* ++ * cxd2880_tnrdmd_dvbt2.c ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * control functions for DVB-T2 ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#include "cxd2880_tnrdmd_dvbt2.h" ++#include "cxd2880_tnrdmd_dvbt2_mon.h" ++ ++static enum cxd2880_ret x_tune_dvbt2_demod_setting(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum cxd2880_dtv_bandwidth ++ bandwidth, ++ enum cxd2880_tnrdmd_clockmode ++ clk_mode) ++{ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x31, ++ 0x02) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x04) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x5D, ++ 0x0B) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_SUB) { ++ u8 data[2] = { 0x01, 0x01 }; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xCE, data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ { ++ u8 data[14] = { 0x07, 0x06, 0x01, 0xF0, ++ 0x00, 0x00, 0x04, 0xB0, 0x00, 0x00, 0x09, 0x9C, 0x0E, ++ 0x4C ++ }; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x20) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x8A, ++ data[0]) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x90, ++ data[1]) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x25) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xF0, &data[2], ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x2A) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xDC, ++ data[4]) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xDE, ++ data[5]) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x2D) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x73, &data[6], ++ 4) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x8F, &data[10], ++ 4) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ { ++ u8 data_a_1[9] = { 0x52, 0x49, 0x2C, 0x51, ++ 0x51, 0x3D, 0x15, 0x29, 0x0C ++ }; ++ u8 data_b_1[9] = { 0x5D, 0x55, 0x32, 0x5C, ++ 0x5C, 0x45, 0x17, 0x2E, 0x0D ++ }; ++ u8 data_c_1[9] = { 0x60, 0x00, 0x34, 0x5E, ++ 0x5E, 0x47, 0x18, 0x2F, 0x0E ++ }; ++ ++ u8 data_a_2[13] = { 0x04, 0xE7, 0x94, 0x92, ++ 0x09, 0xCF, 0x7E, 0xD0, 0x49, 0xCD, 0xCD, 0x1F, 0x5B ++ }; ++ u8 data_b_2[13] = { 0x05, 0x90, 0x27, 0x55, ++ 0x0B, 0x20, 0x8F, 0xD6, 0xEA, 0xC8, 0xC8, 0x23, 0x91 ++ }; ++ u8 data_c_2[13] = { 0x05, 0xB8, 0xD8, 0x00, ++ 0x0B, 0x72, 0x93, 0xF3, 0x00, 0xCD, 0xCD, 0x24, 0x95 ++ }; ++ ++ u8 data_a_3[5] = { 0x0B, 0x6A, 0xC9, 0x03, ++ 0x33 ++ }; ++ u8 data_b_3[5] = { 0x01, 0x02, 0xE4, 0x03, ++ 0x39 ++ }; ++ u8 data_c_3[5] = { 0x01, 0x02, 0xEB, 0x03, ++ 0x3B ++ }; ++ ++ u8 *data_1 = NULL; ++ u8 *data_2 = NULL; ++ u8 *data_3 = NULL; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ data_1 = data_a_1; ++ data_2 = data_a_2; ++ data_3 = data_a_3; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data_1 = data_b_1; ++ data_2 = data_b_2; ++ data_3 = data_b_3; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data_1 = data_c_1; ++ data_2 = data_c_2; ++ data_3 = data_c_3; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x04) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x1D, ++ &data_1[0], 3) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x22, ++ data_1[3]) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x24, ++ data_1[4]) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x26, ++ data_1[5]) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x29, ++ &data_1[6], 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x2D, ++ data_1[8]) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_SUB) { ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x2E, ++ &data_2[0], ++ 6) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x35, ++ &data_2[6], ++ 7) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x3C, ++ &data_3[0], 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x56, ++ &data_3[2], 3) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ switch (bandwidth) { ++ case CXD2880_DTV_BW_8_MHZ: ++ ++ { ++ u8 data_ac[6] = { 0x15, 0x00, 0x00, 0x00, ++ 0x00, 0x00 ++ }; ++ u8 data_b[6] = { 0x14, 0x6A, 0xAA, 0xAA, ++ 0xAB, 0x00 ++ }; ++ u8 *data = NULL; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = data_ac; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = data_b; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x10, ++ data, ++ 6) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x4A, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ { ++ u8 data_a[2] = { 0x19, 0xD2 }; ++ u8 data_bc[2] = { 0x3F, 0xFF }; ++ u8 *data = NULL; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ data = data_a; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = data_bc; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x19, ++ data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ { ++ u8 data_a[2] = { 0x06, 0x2A }; ++ u8 data_b[2] = { 0x06, 0x29 }; ++ u8 data_c[2] = { 0x06, 0x28 }; ++ u8 *data = NULL; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ data = data_a; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = data_b; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = data_c; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x1B, ++ data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ u8 data_a[9] = { 0x28, 0x00, 0x50, 0x00, ++ 0x60, 0x00, 0x00, 0x90, 0x00 ++ }; ++ u8 data_b[9] = { 0x2D, 0x5E, 0x5A, 0xBD, ++ 0x6C, 0xE3, 0x00, 0xA3, 0x55 ++ }; ++ u8 data_c[9] = { 0x2E, 0xAA, 0x5D, 0x55, ++ 0x70, 0x00, 0x00, 0xA8, 0x00 ++ }; ++ u8 *data = NULL; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ data = data_a; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = data_b; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = data_c; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x4B, ++ data, ++ 9) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ break; ++ ++ case CXD2880_DTV_BW_7_MHZ: ++ ++ { ++ u8 data_ac[6] = { 0x18, 0x00, 0x00, 0x00, ++ 0x00, 0x00 ++ }; ++ u8 data_b[6] = { 0x17, 0x55, 0x55, 0x55, ++ 0x55, 0x00 ++ }; ++ u8 *data = NULL; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = data_ac; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = data_b; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x10, ++ data, ++ 6) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x4A, ++ 0x02) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ { ++ u8 data[2] = { 0x3F, 0xFF }; ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x19, ++ data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ { ++ u8 data_a[2] = { 0x06, 0x23 }; ++ u8 data_b[2] = { 0x06, 0x22 }; ++ u8 data_c[2] = { 0x06, 0x21 }; ++ u8 *data = NULL; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ data = data_a; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = data_b; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = data_c; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x1B, ++ data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ u8 data_a[9] = { 0x2D, 0xB6, 0x5B, 0x6D, ++ 0x6D, 0xB6, 0x00, 0xA4, 0x92 ++ }; ++ u8 data_b[9] = { 0x33, 0xDA, 0x67, 0xB4, ++ 0x7C, 0x71, 0x00, 0xBA, 0xAA ++ }; ++ u8 data_c[9] = { 0x35, 0x55, 0x6A, 0xAA, ++ 0x80, 0x00, 0x00, 0xC0, 0x00 ++ }; ++ u8 *data = NULL; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ data = data_a; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = data_b; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = data_c; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x4B, ++ data, ++ 9) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ break; ++ ++ case CXD2880_DTV_BW_6_MHZ: ++ ++ { ++ u8 data_ac[6] = { 0x1C, 0x00, 0x00, 0x00, ++ 0x00, 0x00 ++ }; ++ u8 data_b[6] = { 0x1B, 0x38, 0xE3, 0x8E, ++ 0x39, 0x00 ++ }; ++ u8 *data = NULL; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = data_ac; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = data_b; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x10, ++ data, ++ 6) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x4A, ++ 0x04) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ { ++ u8 data[2] = { 0x3F, 0xFF }; ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x19, ++ data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ { ++ u8 data_a[2] = { 0x06, 0x1C }; ++ u8 data_b[2] = { 0x06, 0x1B }; ++ u8 data_c[2] = { 0x06, 0x1A }; ++ u8 *data = NULL; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ data = data_a; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = data_b; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = data_c; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x1B, ++ data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ u8 data_a[9] = { 0x35, 0x55, 0x6A, 0xAA, ++ 0x80, 0x00, 0x00, 0xC0, 0x00 ++ }; ++ u8 data_b[9] = { 0x3C, 0x7E, 0x78, 0xFC, ++ 0x91, 0x2F, 0x00, 0xD9, 0xC7 ++ }; ++ u8 data_c[9] = { 0x3E, 0x38, 0x7C, 0x71, ++ 0x95, 0x55, 0x00, 0xDF, 0xFF ++ }; ++ u8 *data = NULL; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ data = data_a; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = data_b; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = data_c; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x4B, ++ data, ++ 9) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ break; ++ ++ case CXD2880_DTV_BW_5_MHZ: ++ ++ { ++ u8 data_ac[6] = { 0x21, 0x99, 0x99, 0x99, ++ 0x9A, 0x00 ++ }; ++ u8 data_b[6] = { 0x20, 0xAA, 0xAA, 0xAA, ++ 0xAB, 0x00 ++ }; ++ u8 *data = NULL; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = data_ac; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = data_b; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x10, ++ data, ++ 6) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x4A, ++ 0x06) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ { ++ u8 data[2] = { 0x3F, 0xFF }; ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x19, ++ data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ { ++ u8 data_a[2] = { 0x06, 0x15 }; ++ u8 data_b[2] = { 0x06, 0x15 }; ++ u8 data_c[2] = { 0x06, 0x14 }; ++ u8 *data = NULL; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ data = data_a; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = data_b; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = data_c; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x1B, ++ data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ u8 data_a[9] = { 0x40, 0x00, 0x6A, 0xAA, ++ 0x80, 0x00, 0x00, 0xE6, 0x66 ++ }; ++ u8 data_b[9] = { 0x48, 0x97, 0x78, 0xFC, ++ 0x91, 0x2F, 0x01, 0x05, 0x55 ++ }; ++ u8 data_c[9] = { 0x4A, 0xAA, 0x7C, 0x71, ++ 0x95, 0x55, 0x01, 0x0C, 0xCC ++ }; ++ u8 *data = NULL; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ data = data_a; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = data_b; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = data_c; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x4B, ++ data, ++ 9) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ break; ++ ++ case CXD2880_DTV_BW_1_7_MHZ: ++ ++ { ++ u8 data_a[6] = { 0x68, 0x0F, 0xA2, 0x32, ++ 0xCF, 0x03 ++ }; ++ u8 data_c[6] = { 0x68, 0x0F, 0xA2, 0x32, ++ 0xCF, 0x03 ++ }; ++ u8 data_b[6] = { 0x65, 0x2B, 0xA4, 0xCD, ++ 0xD8, 0x03 ++ }; ++ u8 *data = NULL; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ data = data_a; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = data_c; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = data_b; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x10, ++ data, ++ 6) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x4A, ++ 0x03) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ { ++ u8 data[2] = { 0x3F, 0xFF }; ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x19, ++ data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ { ++ u8 data_a[2] = { 0x06, 0x0C }; ++ u8 data_b[2] = { 0x06, 0x0C }; ++ u8 data_c[2] = { 0x06, 0x0B }; ++ u8 *data = NULL; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ data = data_a; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = data_b; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = data_c; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x1B, ++ data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ u8 data_a[9] = { 0x40, 0x00, 0x6A, 0xAA, ++ 0x80, 0x00, 0x02, 0xC9, 0x8F ++ }; ++ u8 data_b[9] = { 0x48, 0x97, 0x78, 0xFC, ++ 0x91, 0x2F, 0x03, 0x29, 0x5D ++ }; ++ u8 data_c[9] = { 0x4A, 0xAA, 0x7C, 0x71, ++ 0x95, 0x55, 0x03, 0x40, 0x7D ++ }; ++ u8 *data = NULL; ++ ++ switch (clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ data = data_a; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ data = data_b; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ data = data_c; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x4B, ++ data, ++ 9) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ break; ++ ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xFD, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++static enum cxd2880_ret x_sleep_dvbt2_demod_setting(struct cxd2880_tnrdmd ++ *tnr_dmd) ++{ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ u8 data[] = { 0, 1, 0, 2, ++ 0, 4, 0, 8, 0, 16, 0, 32 ++ }; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x1D) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x47, data, ++ 12) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ return CXD2880_RESULT_OK; ++} ++ ++static enum cxd2880_ret dvbt2_set_profile(struct cxd2880_tnrdmd *tnr_dmd, ++ enum cxd2880_dvbt2_profile profile) ++{ ++ u8 t2_mode_tune_mode = 0; ++ u8 seq_not2_dtime = 0; ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ { ++ u8 dtime1 = 0; ++ u8 dtime2 = 0; ++ ++ switch (tnr_dmd->clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ dtime1 = 0x27; ++ dtime2 = 0x0C; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ dtime1 = 0x2C; ++ dtime2 = 0x0D; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ dtime1 = 0x2E; ++ dtime2 = 0x0E; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ switch (profile) { ++ case CXD2880_DVBT2_PROFILE_BASE: ++ t2_mode_tune_mode = 0x01; ++ seq_not2_dtime = dtime2; ++ break; ++ ++ case CXD2880_DVBT2_PROFILE_LITE: ++ t2_mode_tune_mode = 0x05; ++ seq_not2_dtime = dtime1; ++ break; ++ ++ case CXD2880_DVBT2_PROFILE_ANY: ++ t2_mode_tune_mode = 0x00; ++ seq_not2_dtime = dtime1; ++ break; ++ ++ default: ++ return CXD2880_RESULT_ERROR_ARG; ++ } ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x2E) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x10, ++ t2_mode_tune_mode) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x04) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x2C, ++ seq_not2_dtime) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_tune1(struct cxd2880_tnrdmd *tnr_dmd, ++ struct cxd2880_dvbt2_tune_param ++ *tune_param) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!tune_param)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) && ++ (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if ((tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) && ++ (tune_param->profile == CXD2880_DVBT2_PROFILE_ANY)) ++ return CXD2880_RESULT_ERROR_NOSUPPORT; ++ ++ ret = ++ cxd2880_tnrdmd_common_tune_setting1(tnr_dmd, CXD2880_DTV_SYS_DVBT2, ++ tune_param->center_freq_khz, ++ tune_param->bandwidth, 0, 0); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ ret = ++ x_tune_dvbt2_demod_setting(tnr_dmd, tune_param->bandwidth, ++ tnr_dmd->clk_mode); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ ret = ++ x_tune_dvbt2_demod_setting(tnr_dmd->diver_sub, ++ tune_param->bandwidth, ++ tnr_dmd->diver_sub->clk_mode); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ ret = dvbt2_set_profile(tnr_dmd, tune_param->profile); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ ret = ++ dvbt2_set_profile(tnr_dmd->diver_sub, tune_param->profile); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ if (tune_param->data_plp_id == CXD2880_DVBT2_TUNE_PARAM_PLPID_AUTO) { ++ ret = cxd2880_tnrdmd_dvbt2_set_plp_cfg(tnr_dmd, 1, 0); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } else { ++ ret = ++ cxd2880_tnrdmd_dvbt2_set_plp_cfg(tnr_dmd, 0, ++ (u8)(tune_param->data_plp_id)); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_tune2(struct cxd2880_tnrdmd *tnr_dmd, ++ struct cxd2880_dvbt2_tune_param ++ *tune_param) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!tune_param)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) && ++ (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ { ++ u8 en_fef_intmtnt_ctrl = 1; ++ ++ switch (tune_param->profile) { ++ case CXD2880_DVBT2_PROFILE_BASE: ++ en_fef_intmtnt_ctrl = tnr_dmd->en_fef_intmtnt_base; ++ break; ++ case CXD2880_DVBT2_PROFILE_LITE: ++ en_fef_intmtnt_ctrl = tnr_dmd->en_fef_intmtnt_lite; ++ break; ++ case CXD2880_DVBT2_PROFILE_ANY: ++ if (tnr_dmd->en_fef_intmtnt_base && ++ tnr_dmd->en_fef_intmtnt_lite) ++ en_fef_intmtnt_ctrl = 1; ++ else ++ en_fef_intmtnt_ctrl = 0; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_ARG; ++ } ++ ++ ret = ++ cxd2880_tnrdmd_common_tune_setting2(tnr_dmd, ++ CXD2880_DTV_SYS_DVBT2, ++ en_fef_intmtnt_ctrl); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ tnr_dmd->state = CXD2880_TNRDMD_STATE_ACTIVE; ++ tnr_dmd->frequency_khz = tune_param->center_freq_khz; ++ tnr_dmd->sys = CXD2880_DTV_SYS_DVBT2; ++ tnr_dmd->bandwidth = tune_param->bandwidth; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ tnr_dmd->diver_sub->state = CXD2880_TNRDMD_STATE_ACTIVE; ++ tnr_dmd->diver_sub->frequency_khz = tune_param->center_freq_khz; ++ tnr_dmd->diver_sub->sys = CXD2880_DTV_SYS_DVBT2; ++ tnr_dmd->diver_sub->bandwidth = tune_param->bandwidth; ++ } ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_sleep_setting(struct cxd2880_tnrdmd ++ *tnr_dmd) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) && ++ (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = x_sleep_dvbt2_demod_setting(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ ret = x_sleep_dvbt2_demod_setting(tnr_dmd->diver_sub); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_check_demod_lock(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum ++ cxd2880_tnrdmd_lock_result ++ *lock) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ u8 sync_stat = 0; ++ u8 ts_lock = 0; ++ u8 unlock_detected = 0; ++ u8 unlock_detected_sub = 0; ++ ++ if ((!tnr_dmd) || (!lock)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = ++ cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd, &sync_stat, &ts_lock, ++ &unlock_detected); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE) { ++ if (sync_stat == 6) ++ *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED; ++ else if (unlock_detected) ++ *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED; ++ else ++ *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT; ++ ++ return ret; ++ } ++ ++ if (sync_stat == 6) { ++ *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED; ++ return ret; ++ } ++ ++ ret = ++ cxd2880_tnrdmd_dvbt2_mon_sync_stat_sub(tnr_dmd, &sync_stat, ++ &unlock_detected_sub); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (sync_stat == 6) ++ *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED; ++ else if (unlock_detected && unlock_detected_sub) ++ *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED; ++ else ++ *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT; ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_check_ts_lock(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum ++ cxd2880_tnrdmd_lock_result ++ *lock) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ u8 sync_stat = 0; ++ u8 ts_lock = 0; ++ u8 unlock_detected = 0; ++ u8 unlock_detected_sub = 0; ++ ++ if ((!tnr_dmd) || (!lock)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = ++ cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd, &sync_stat, &ts_lock, ++ &unlock_detected); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE) { ++ if (ts_lock) ++ *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED; ++ else if (unlock_detected) ++ *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED; ++ else ++ *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT; ++ ++ return ret; ++ } ++ ++ if (ts_lock) { ++ *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED; ++ return ret; ++ } else if (!unlock_detected) { ++ *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT; ++ return ret; ++ } ++ ++ ret = ++ cxd2880_tnrdmd_dvbt2_mon_sync_stat_sub(tnr_dmd, &sync_stat, ++ &unlock_detected_sub); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (unlock_detected && unlock_detected_sub) ++ *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED; ++ else ++ *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT; ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_set_plp_cfg(struct cxd2880_tnrdmd ++ *tnr_dmd, u8 auto_plp, ++ u8 plp_id) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) && ++ (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x23) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (!auto_plp) { ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xAF, ++ plp_id) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xAD, ++ auto_plp ? 0x00 : 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_diver_fef_setting(struct cxd2880_tnrdmd ++ *tnr_dmd) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE) ++ return CXD2880_RESULT_OK; ++ ++ { ++ struct cxd2880_dvbt2_ofdm ofdm; ++ ++ ret = cxd2880_tnrdmd_dvbt2_mon_ofdm(tnr_dmd, &ofdm); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (!ofdm.mixed) ++ return CXD2880_RESULT_OK; ++ } ++ ++ { ++ u8 data[] = { 0, 8, 0, 16, ++ 0, 32, 0, 64, 0, 128, 1, 0 ++ }; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x1D) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x47, data, ++ 12) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_check_l1post_valid(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ u8 *l1_post_valid) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ u8 data; ++ ++ if ((!tnr_dmd) || (!l1_post_valid)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) && ++ (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0B) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x86, &data, ++ 1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ *l1_post_valid = data & 0x01; ++ ++ return ret; ++} +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt2.h b/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt2.h +new file mode 100644 +index 0000000000000000000000000000000000000000..8735280f0143ec5a7304dbeca39a510e346a0071 +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt2.h +@@ -0,0 +1,82 @@ ++/* ++ * cxd2880_tnrdmd_dvbt2.h ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * control interface for DVB-T2 ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#ifndef CXD2880_TNRDMD_DVBT2_H ++#define CXD2880_TNRDMD_DVBT2_H ++ ++#include "cxd2880_common.h" ++#include "cxd2880_tnrdmd.h" ++ ++enum cxd2880_tnrdmd_dvbt2_tune_info { ++ CXD2880_TNRDMD_DVBT2_TUNE_INFO_OK, ++ CXD2880_TNRDMD_DVBT2_TUNE_INFO_INVALID_PLP_ID ++}; ++ ++struct cxd2880_dvbt2_tune_param { ++ u32 center_freq_khz; ++ enum cxd2880_dtv_bandwidth bandwidth; ++ u16 data_plp_id; ++ enum cxd2880_dvbt2_profile profile; ++ enum cxd2880_tnrdmd_dvbt2_tune_info tune_info; ++}; ++ ++#define CXD2880_DVBT2_TUNE_PARAM_PLPID_AUTO 0xFFFF ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_tune1(struct cxd2880_tnrdmd *tnr_dmd, ++ struct cxd2880_dvbt2_tune_param ++ *tune_param); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_tune2(struct cxd2880_tnrdmd *tnr_dmd, ++ struct cxd2880_dvbt2_tune_param ++ *tune_param); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_sleep_setting(struct cxd2880_tnrdmd ++ *tnr_dmd); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_check_demod_lock(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum ++ cxd2880_tnrdmd_lock_result ++ *lock); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_check_ts_lock(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum ++ cxd2880_tnrdmd_lock_result ++ *lock); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_set_plp_cfg(struct cxd2880_tnrdmd ++ *tnr_dmd, u8 auto_plp, ++ u8 plp_id); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_diver_fef_setting(struct cxd2880_tnrdmd ++ *tnr_dmd); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_check_l1post_valid(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ u8 *l1_post_valid); ++ ++#endif +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt2_mon.c b/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt2_mon.c +new file mode 100644 +index 0000000000000000000000000000000000000000..235db16f4a08faf05db3aea737251fa5f82f143e +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt2_mon.c +@@ -0,0 +1,2523 @@ ++/* ++ * cxd2880_tnrdmd_dvbt2_mon.c ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * DVB-T2 monitor functions ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#include "cxd2880_tnrdmd_mon.h" ++#include "cxd2880_tnrdmd_dvbt2.h" ++#include "cxd2880_tnrdmd_dvbt2_mon.h" ++#include "cxd2880_math.h" ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_sync_stat(struct cxd2880_tnrdmd ++ *tnr_dmd, u8 *sync_stat, ++ u8 *ts_lock_stat, ++ u8 *unlock_detected) ++{ ++ if ((!tnr_dmd) || (!sync_stat) || (!ts_lock_stat) || (!unlock_detected)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0B) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ { ++ u8 data; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x10, &data, ++ sizeof(data)) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ *sync_stat = data & 0x07; ++ *ts_lock_stat = ((data & 0x20) ? 1 : 0); ++ *unlock_detected = ((data & 0x10) ? 1 : 0); ++ } ++ ++ if (*sync_stat == 0x07) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_sync_stat_sub(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ u8 *sync_stat, ++ u8 *unlock_detected) ++{ ++ u8 ts_lock_stat = 0; ++ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!sync_stat) || (!unlock_detected)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ ret = ++ cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd->diver_sub, sync_stat, ++ &ts_lock_stat, unlock_detected); ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_carrier_offset(struct cxd2880_tnrdmd ++ *tnr_dmd, int *offset) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!offset)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ { ++ u8 data[4]; ++ u32 ctl_val = 0; ++ u8 sync_state = 0; ++ u8 ts_lock = 0; ++ u8 unlock_detected = 0; ++ ++ if (slvt_freeze_reg(tnr_dmd) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ ret = ++ cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd, &sync_state, ++ &ts_lock, ++ &unlock_detected); ++ if (ret != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (sync_state != 6) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0B) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x30, data, ++ sizeof(data)) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ slvt_unfreeze_reg(tnr_dmd); ++ ++ ctl_val = ++ ((data[0] & 0x0F) << 24) | (data[1] << 16) | (data[2] << 8) ++ | (data[3]); ++ *offset = cxd2880_convert2s_complement(ctl_val, 28); ++ ++ switch (tnr_dmd->bandwidth) { ++ case CXD2880_DTV_BW_1_7_MHZ: ++ *offset = -1 * ((*offset) / 582); ++ break; ++ case CXD2880_DTV_BW_5_MHZ: ++ case CXD2880_DTV_BW_6_MHZ: ++ case CXD2880_DTV_BW_7_MHZ: ++ case CXD2880_DTV_BW_8_MHZ: ++ *offset = ++ -1 * ((*offset) * (u8)tnr_dmd->bandwidth / 940); ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ } ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_carrier_offset_sub(struct ++ cxd2880_tnrdmd ++ *tnr_dmd, ++ int *offset) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!offset)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ ret = ++ cxd2880_tnrdmd_dvbt2_mon_carrier_offset(tnr_dmd->diver_sub, offset); ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_l1_pre(struct cxd2880_tnrdmd *tnr_dmd, ++ struct cxd2880_dvbt2_l1pre ++ *l1_pre) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!l1_pre)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ { ++ u8 data[37]; ++ u8 sync_state = 0; ++ u8 ts_lock = 0; ++ u8 unlock_detected = 0; ++ u8 version = 0; ++ enum cxd2880_dvbt2_profile profile; ++ ++ if (slvt_freeze_reg(tnr_dmd) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ ret = ++ cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd, &sync_state, ++ &ts_lock, ++ &unlock_detected); ++ if (ret != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return ret; ++ } ++ ++ if (sync_state < 5) { ++ if (tnr_dmd->diver_mode == ++ CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ ret = ++ cxd2880_tnrdmd_dvbt2_mon_sync_stat_sub ++ (tnr_dmd, &sync_state, &unlock_detected); ++ if (ret != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return ret; ++ } ++ ++ if (sync_state < 5) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ } else { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ } ++ ++ ret = cxd2880_tnrdmd_dvbt2_mon_profile(tnr_dmd, &profile); ++ if (ret != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return ret; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0B) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x61, data, ++ sizeof(data)) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ slvt_unfreeze_reg(tnr_dmd); ++ ++ l1_pre->type = (enum cxd2880_dvbt2_l1pre_type)data[0]; ++ l1_pre->bw_ext = data[1] & 0x01; ++ l1_pre->s1 = (enum cxd2880_dvbt2_s1)(data[2] & 0x07); ++ l1_pre->s2 = data[3] & 0x0F; ++ l1_pre->l1_rep = data[4] & 0x01; ++ l1_pre->gi = (enum cxd2880_dvbt2_guard)(data[5] & 0x07); ++ l1_pre->papr = (enum cxd2880_dvbt2_papr)(data[6] & 0x0F); ++ l1_pre->mod = ++ (enum cxd2880_dvbt2_l1post_constell)(data[7] & 0x0F); ++ l1_pre->cr = (enum cxd2880_dvbt2_l1post_cr)(data[8] & 0x03); ++ l1_pre->fec = ++ (enum cxd2880_dvbt2_l1post_fec_type)(data[9] & 0x03); ++ l1_pre->l1_post_size = (data[10] & 0x03) << 16; ++ l1_pre->l1_post_size |= (data[11]) << 8; ++ l1_pre->l1_post_size |= (data[12]); ++ l1_pre->l1_post_info_size = (data[13] & 0x03) << 16; ++ l1_pre->l1_post_info_size |= (data[14]) << 8; ++ l1_pre->l1_post_info_size |= (data[15]); ++ l1_pre->pp = (enum cxd2880_dvbt2_pp)(data[16] & 0x0F); ++ l1_pre->tx_id_availability = data[17]; ++ l1_pre->cell_id = (data[18] << 8); ++ l1_pre->cell_id |= (data[19]); ++ l1_pre->network_id = (data[20] << 8); ++ l1_pre->network_id |= (data[21]); ++ l1_pre->sys_id = (data[22] << 8); ++ l1_pre->sys_id |= (data[23]); ++ l1_pre->num_frames = data[24]; ++ l1_pre->num_symbols = (data[25] & 0x0F) << 8; ++ l1_pre->num_symbols |= data[26]; ++ l1_pre->regen = data[27] & 0x07; ++ l1_pre->post_ext = data[28] & 0x01; ++ l1_pre->num_rf_freqs = data[29] & 0x07; ++ l1_pre->rf_idx = data[30] & 0x07; ++ version = (data[31] & 0x03) << 2; ++ version |= (data[32] & 0xC0) >> 6; ++ l1_pre->t2_version = (enum cxd2880_dvbt2_version)version; ++ l1_pre->l1_post_scrambled = (data[32] & 0x20) >> 5; ++ l1_pre->t2_base_lite = (data[32] & 0x10) >> 4; ++ l1_pre->crc32 = (data[33] << 24); ++ l1_pre->crc32 |= (data[34] << 16); ++ l1_pre->crc32 |= (data[35] << 8); ++ l1_pre->crc32 |= data[36]; ++ ++ if (profile == CXD2880_DVBT2_PROFILE_BASE) { ++ switch ((l1_pre->s2 >> 1)) { ++ case CXD2880_DVBT2_BASE_S2_M1K_G_ANY: ++ l1_pre->fft_mode = CXD2880_DVBT2_M1K; ++ break; ++ case CXD2880_DVBT2_BASE_S2_M2K_G_ANY: ++ l1_pre->fft_mode = CXD2880_DVBT2_M2K; ++ break; ++ case CXD2880_DVBT2_BASE_S2_M4K_G_ANY: ++ l1_pre->fft_mode = CXD2880_DVBT2_M4K; ++ break; ++ case CXD2880_DVBT2_BASE_S2_M8K_G_DVBT: ++ case CXD2880_DVBT2_BASE_S2_M8K_G_DVBT2: ++ l1_pre->fft_mode = CXD2880_DVBT2_M8K; ++ break; ++ case CXD2880_DVBT2_BASE_S2_M16K_G_ANY: ++ l1_pre->fft_mode = CXD2880_DVBT2_M16K; ++ break; ++ case CXD2880_DVBT2_BASE_S2_M32K_G_DVBT: ++ case CXD2880_DVBT2_BASE_S2_M32K_G_DVBT2: ++ l1_pre->fft_mode = CXD2880_DVBT2_M32K; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ } else if (profile == CXD2880_DVBT2_PROFILE_LITE) { ++ switch ((l1_pre->s2 >> 1)) { ++ case CXD2880_DVBT2_LITE_S2_M2K_G_ANY: ++ l1_pre->fft_mode = CXD2880_DVBT2_M2K; ++ break; ++ case CXD2880_DVBT2_LITE_S2_M4K_G_ANY: ++ l1_pre->fft_mode = CXD2880_DVBT2_M4K; ++ break; ++ case CXD2880_DVBT2_LITE_S2_M8K_G_DVBT: ++ case CXD2880_DVBT2_LITE_S2_M8K_G_DVBT2: ++ l1_pre->fft_mode = CXD2880_DVBT2_M8K; ++ break; ++ case CXD2880_DVBT2_LITE_S2_M16K_G_DVBT: ++ case CXD2880_DVBT2_LITE_S2_M16K_G_DVBT2: ++ l1_pre->fft_mode = CXD2880_DVBT2_M16K; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ } else { ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ ++ l1_pre->mixed = l1_pre->s2 & 0x01; ++ } ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_version(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum cxd2880_dvbt2_version ++ *ver) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ u8 version = 0; ++ ++ if ((!tnr_dmd) || (!ver)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ { ++ u8 data[2]; ++ u8 sync_state = 0; ++ u8 ts_lock = 0; ++ u8 unlock_detected = 0; ++ ++ if (slvt_freeze_reg(tnr_dmd) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ ret = ++ cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd, &sync_state, ++ &ts_lock, ++ &unlock_detected); ++ if (ret != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (sync_state < 5) { ++ if (tnr_dmd->diver_mode == ++ CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ ret = ++ cxd2880_tnrdmd_dvbt2_mon_sync_stat_sub ++ (tnr_dmd, &sync_state, &unlock_detected); ++ if (ret != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return ret; ++ } ++ ++ if (sync_state < 5) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ } else { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0B) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x80, data, ++ sizeof(data)) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ slvt_unfreeze_reg(tnr_dmd); ++ ++ version = ((data[0] & 0x03) << 2); ++ version |= ((data[1] & 0xC0) >> 6); ++ *ver = (enum cxd2880_dvbt2_version)version; ++ } ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_ofdm(struct cxd2880_tnrdmd *tnr_dmd, ++ struct cxd2880_dvbt2_ofdm *ofdm) ++{ ++ if ((!tnr_dmd) || (!ofdm)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ { ++ u8 data[5]; ++ u8 sync_state = 0; ++ u8 ts_lock = 0; ++ u8 unlock_detected = 0; ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if (slvt_freeze_reg(tnr_dmd) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ ret = ++ cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd, &sync_state, ++ &ts_lock, ++ &unlock_detected); ++ if (ret != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (sync_state != 6) { ++ slvt_unfreeze_reg(tnr_dmd); ++ ++ ret = CXD2880_RESULT_ERROR_HW_STATE; ++ ++ if (tnr_dmd->diver_mode == ++ CXD2880_TNRDMD_DIVERMODE_MAIN) ++ ret = ++ cxd2880_tnrdmd_dvbt2_mon_ofdm( ++ tnr_dmd->diver_sub, ofdm); ++ ++ return ret; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0B) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x1D, data, ++ sizeof(data)) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ slvt_unfreeze_reg(tnr_dmd); ++ ++ ofdm->mixed = ((data[0] & 0x20) ? 1 : 0); ++ ofdm->is_miso = ((data[0] & 0x10) >> 4); ++ ofdm->mode = (enum cxd2880_dvbt2_mode)(data[0] & 0x07); ++ ofdm->gi = (enum cxd2880_dvbt2_guard)((data[1] & 0x70) >> 4); ++ ofdm->pp = (enum cxd2880_dvbt2_pp)(data[1] & 0x07); ++ ofdm->bw_ext = (data[2] & 0x10) >> 4; ++ ofdm->papr = (enum cxd2880_dvbt2_papr)(data[2] & 0x0F); ++ ofdm->num_symbols = (data[3] << 8) | data[4]; ++ } ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_data_plps(struct cxd2880_tnrdmd ++ *tnr_dmd, u8 *plp_ids, ++ u8 *num_plps) ++{ ++ if ((!tnr_dmd) || (!num_plps)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ { ++ u8 l1_post_ok = 0; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0B) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (slvt_freeze_reg(tnr_dmd) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x86, ++ &l1_post_ok, ++ 1) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (!(l1_post_ok & 0x01)) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xC1, num_plps, ++ 1) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (*num_plps == 0) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_OTHER; ++ } ++ ++ if (!plp_ids) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_OK; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xC2, plp_ids, ++ ((*num_plps > ++ 62) ? 62 : *num_plps)) != ++ CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (*num_plps > 62) { ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0C) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x10, ++ plp_ids + 62, ++ *num_plps - 62) != ++ CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ } ++ ++ slvt_unfreeze_reg(tnr_dmd); ++ } ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_active_plp(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum ++ cxd2880_dvbt2_plp_btype ++ type, ++ struct cxd2880_dvbt2_plp ++ *plp_info) ++{ ++ if ((!tnr_dmd) || (!plp_info)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ { ++ u8 data[20]; ++ u8 addr = 0; ++ u8 index = 0; ++ u8 l1_post_ok = 0; ++ ++ if (slvt_freeze_reg(tnr_dmd) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0B) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x86, ++ &l1_post_ok, ++ 1) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (!l1_post_ok) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ ++ if (type == CXD2880_DVBT2_PLP_COMMON) ++ addr = 0xA9; ++ else ++ addr = 0x96; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, addr, data, ++ sizeof(data)) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ slvt_unfreeze_reg(tnr_dmd); ++ ++ if ((type == CXD2880_DVBT2_PLP_COMMON) && (data[13] == 0)) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ plp_info->id = data[index++]; ++ plp_info->type = ++ (enum cxd2880_dvbt2_plp_type)(data[index++] & 0x07); ++ plp_info->payload = ++ (enum cxd2880_dvbt2_plp_payload)(data[index++] & 0x1F); ++ plp_info->ff = data[index++] & 0x01; ++ plp_info->first_rf_idx = data[index++] & 0x07; ++ plp_info->first_frm_idx = data[index++]; ++ plp_info->group_id = data[index++]; ++ plp_info->plp_cr = ++ (enum cxd2880_dvbt2_plp_code_rate)(data[index++] & 0x07); ++ plp_info->constell = ++ (enum cxd2880_dvbt2_plp_constell)(data[index++] & 0x07); ++ plp_info->rot = data[index++] & 0x01; ++ plp_info->fec = ++ (enum cxd2880_dvbt2_plp_fec)(data[index++] & 0x03); ++ plp_info->num_blocks_max = (u16)((data[index++] & 0x03)) << 8; ++ plp_info->num_blocks_max |= data[index++]; ++ plp_info->frm_int = data[index++]; ++ plp_info->til_len = data[index++]; ++ plp_info->til_type = data[index++] & 0x01; ++ ++ plp_info->in_band_a_flag = data[index++] & 0x01; ++ plp_info->rsvd = data[index++] << 8; ++ plp_info->rsvd |= data[index++]; ++ ++ plp_info->in_band_b_flag = ++ (u8)((plp_info->rsvd & 0x8000) >> 15); ++ plp_info->plp_mode = ++ (enum cxd2880_dvbt2_plp_mode)((plp_info->rsvd & 0x000C) >> ++ 2); ++ plp_info->static_flag = (u8)((plp_info->rsvd & 0x0002) >> 1); ++ plp_info->static_padding_flag = (u8)(plp_info->rsvd & 0x0001); ++ plp_info->rsvd = (u16)((plp_info->rsvd & 0x7FF0) >> 4); ++ } ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_data_plp_error(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ u8 *plp_error) ++{ ++ if ((!tnr_dmd) || (!plp_error)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (slvt_freeze_reg(tnr_dmd) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ { ++ u8 data; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0B) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x86, &data, ++ 1) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if ((data & 0x01) == 0x00) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xC0, &data, ++ 1) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ slvt_unfreeze_reg(tnr_dmd); ++ ++ *plp_error = data & 0x01; ++ } ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_l1_change(struct cxd2880_tnrdmd ++ *tnr_dmd, u8 *l1_change) ++{ ++ if ((!tnr_dmd) || (!l1_change)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ { ++ u8 data; ++ u8 sync_state = 0; ++ u8 ts_lock = 0; ++ u8 unlock_detected = 0; ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if (slvt_freeze_reg(tnr_dmd) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ ret = ++ cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd, &sync_state, ++ &ts_lock, ++ &unlock_detected); ++ if (ret != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (sync_state < 5) { ++ if (tnr_dmd->diver_mode == ++ CXD2880_TNRDMD_DIVERMODE_MAIN) { ++ ret = ++ cxd2880_tnrdmd_dvbt2_mon_sync_stat_sub ++ (tnr_dmd, &sync_state, &unlock_detected); ++ if (ret != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return ret; ++ } ++ ++ if (sync_state < 5) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ } else { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0B) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x5F, &data, ++ sizeof(data)) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ *l1_change = data & 0x01; ++ if (*l1_change) { ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x22) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x16, ++ 0x01) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ } ++ slvt_unfreeze_reg(tnr_dmd); ++ } ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_l1_post(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ struct cxd2880_dvbt2_l1post ++ *l1_post) ++{ ++ if ((!tnr_dmd) || (!l1_post)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ { ++ u8 data[16]; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0B) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x86, data, ++ sizeof(data)) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (!(data[0] & 0x01)) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ l1_post->sub_slices_per_frame = (data[1] & 0x7F) << 8; ++ l1_post->sub_slices_per_frame |= data[2]; ++ l1_post->num_plps = data[3]; ++ l1_post->num_aux = data[4] & 0x0F; ++ l1_post->aux_cfg_rfu = data[5]; ++ l1_post->rf_idx = data[6] & 0x07; ++ l1_post->freq = data[7] << 24; ++ l1_post->freq |= data[8] << 16; ++ l1_post->freq |= data[9] << 8; ++ l1_post->freq |= data[10]; ++ l1_post->fef_type = data[11] & 0x0F; ++ l1_post->fef_length = data[12] << 16; ++ l1_post->fef_length |= data[13] << 8; ++ l1_post->fef_length |= data[14]; ++ l1_post->fef_intvl = data[15]; ++ } ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_bbheader(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum cxd2880_dvbt2_plp_btype ++ type, ++ struct cxd2880_dvbt2_bbheader ++ *bbheader) ++{ ++ if ((!tnr_dmd) || (!bbheader)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (slvt_freeze_reg(tnr_dmd) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ { ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ u8 sync_state = 0; ++ u8 ts_lock = 0; ++ u8 unlock_detected = 0; ++ ++ ret = ++ cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd, &sync_state, ++ &ts_lock, ++ &unlock_detected); ++ if (ret != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return ret; ++ } ++ ++ if (!ts_lock) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0B) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (type == CXD2880_DVBT2_PLP_COMMON) { ++ u8 l1_post_ok; ++ u8 data; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x86, ++ &l1_post_ok, ++ 1) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (!(l1_post_ok & 0x01)) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xB6, &data, ++ 1) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (data == 0) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ } ++ ++ { ++ u8 data[14]; ++ u8 addr = 0; ++ ++ if (type == CXD2880_DVBT2_PLP_COMMON) ++ addr = 0x51; ++ else ++ addr = 0x42; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, addr, data, ++ sizeof(data)) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ slvt_unfreeze_reg(tnr_dmd); ++ ++ bbheader->stream_input = ++ (enum cxd2880_dvbt2_stream)((data[0] >> 6) & 0x03); ++ bbheader->is_single_input_stream = (u8)((data[0] >> 5) & 0x01); ++ bbheader->is_constant_coding_modulation = ++ (u8)((data[0] >> 4) & 0x01); ++ bbheader->issy_indicator = (u8)((data[0] >> 3) & 0x01); ++ bbheader->null_packet_deletion = (u8)((data[0] >> 2) & 0x01); ++ bbheader->ext = (u8)(data[0] & 0x03); ++ ++ bbheader->input_stream_identifier = data[1]; ++ bbheader->plp_mode = ++ (data[3] & 0x01) ? CXD2880_DVBT2_PLP_MODE_HEM : ++ CXD2880_DVBT2_PLP_MODE_NM; ++ bbheader->data_field_length = (u16)((data[4] << 8) | data[5]); ++ ++ if (bbheader->plp_mode == CXD2880_DVBT2_PLP_MODE_NM) { ++ bbheader->user_packet_length = ++ (u16)((data[6] << 8) | data[7]); ++ bbheader->sync_byte = data[8]; ++ bbheader->issy = 0; ++ } else { ++ bbheader->user_packet_length = 0; ++ bbheader->sync_byte = 0; ++ bbheader->issy = ++ (u32)((data[11] << 16) | (data[12] << 8) | ++ data[13]); ++ } ++ } ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_in_bandb_ts_rate(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum ++ cxd2880_dvbt2_plp_btype ++ type, ++ u32 *ts_rate_bps) ++{ ++ if ((!tnr_dmd) || (!ts_rate_bps)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (slvt_freeze_reg(tnr_dmd) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ { ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ u8 sync_state = 0; ++ u8 ts_lock = 0; ++ u8 unlock_detected = 0; ++ ++ ret = ++ cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd, &sync_state, ++ &ts_lock, ++ &unlock_detected); ++ if (ret != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return ret; ++ } ++ ++ if (!ts_lock) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0B) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ { ++ u8 l1_post_ok = 0; ++ u8 addr = 0; ++ u8 data = 0; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x86, ++ &l1_post_ok, ++ 1) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (!(l1_post_ok & 0x01)) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ ++ if (type == CXD2880_DVBT2_PLP_COMMON) ++ addr = 0xBA; ++ else ++ addr = 0xA7; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, addr, &data, ++ 1) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if ((data & 0x80) == 0x00) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x25) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ { ++ u8 data[4]; ++ u8 addr = 0; ++ ++ if (type == CXD2880_DVBT2_PLP_COMMON) ++ addr = 0xA6; ++ else ++ addr = 0xAA; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, addr, &data[0], ++ 4) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ *ts_rate_bps = ++ (u32)(((data[0] & 0x07) << 24) | (data[1] << 16) | ++ (data[2] << 8) | data[3]); ++ } ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_spectrum_sense(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum ++ cxd2880_tnrdmd_spectrum_sense ++ *sense) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ u8 sync_state = 0; ++ u8 ts_lock = 0; ++ u8 early_unlock = 0; ++ ++ if ((!tnr_dmd) || (!sense)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (slvt_freeze_reg(tnr_dmd) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ ret = ++ cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd, &sync_state, &ts_lock, ++ &early_unlock); ++ if (ret != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return ret; ++ } ++ ++ if (sync_state != 6) { ++ slvt_unfreeze_reg(tnr_dmd); ++ ++ ret = CXD2880_RESULT_ERROR_HW_STATE; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) ++ ret = ++ cxd2880_tnrdmd_dvbt2_mon_spectrum_sense( ++ tnr_dmd->diver_sub, sense); ++ ++ return ret; ++ } ++ ++ { ++ u8 data = 0; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0B) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x2F, &data, ++ sizeof(data)) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ slvt_unfreeze_reg(tnr_dmd); ++ ++ *sense = ++ (data & 0x01) ? CXD2880_TNRDMD_SPECTRUM_INV : ++ CXD2880_TNRDMD_SPECTRUM_NORMAL; ++ } ++ ++ return CXD2880_RESULT_OK; ++} ++ ++static enum cxd2880_ret dvbt2_read_snr_reg(struct cxd2880_tnrdmd *tnr_dmd, ++ u16 *reg_value) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!reg_value)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ { ++ u8 sync_state = 0; ++ u8 ts_lock = 0; ++ u8 unlock_detected = 0; ++ u8 data[2]; ++ ++ if (slvt_freeze_reg(tnr_dmd) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ ret = ++ cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd, &sync_state, ++ &ts_lock, ++ &unlock_detected); ++ if (ret != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (sync_state != 6) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0B) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x13, data, ++ sizeof(data)) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ slvt_unfreeze_reg(tnr_dmd); ++ ++ *reg_value = (data[0] << 8) | data[1]; ++ } ++ ++ return ret; ++} ++ ++static enum cxd2880_ret dvbt2_calc_snr(struct cxd2880_tnrdmd *tnr_dmd, ++ u32 reg_value, int *snr) ++{ ++ if ((!tnr_dmd) || (!snr)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (reg_value == 0) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ if (reg_value > 10876) ++ reg_value = 10876; ++ ++ *snr = ++ 10 * 10 * ((int)cxd2880_math_log10(reg_value) - ++ (int)cxd2880_math_log10(12600 - reg_value)); ++ *snr += 32000; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_snr(struct cxd2880_tnrdmd *tnr_dmd, ++ int *snr) ++{ ++ u16 reg_value = 0; ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!snr)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ *snr = -1000 * 1000; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE) { ++ ret = dvbt2_read_snr_reg(tnr_dmd, ®_value); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ ret = dvbt2_calc_snr(tnr_dmd, reg_value, snr); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } else { ++ int snr_main = 0; ++ int snr_sub = 0; ++ ++ ret = ++ cxd2880_tnrdmd_dvbt2_mon_snr_diver(tnr_dmd, snr, &snr_main, ++ &snr_sub); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_snr_diver(struct cxd2880_tnrdmd ++ *tnr_dmd, int *snr, ++ int *snr_main, int *snr_sub) ++{ ++ u16 reg_value = 0; ++ u32 reg_value_sum = 0; ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!snr) || (!snr_main) || (!snr_sub)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ *snr = -1000 * 1000; ++ *snr_main = -1000 * 1000; ++ *snr_sub = -1000 * 1000; ++ ++ if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = dvbt2_read_snr_reg(tnr_dmd, ®_value); ++ if (ret == CXD2880_RESULT_OK) { ++ ret = dvbt2_calc_snr(tnr_dmd, reg_value, snr_main); ++ if (ret != CXD2880_RESULT_OK) ++ reg_value = 0; ++ } else if (ret == CXD2880_RESULT_ERROR_HW_STATE) { ++ reg_value = 0; ++ } else { ++ return ret; ++ } ++ ++ reg_value_sum += reg_value; ++ ++ ret = dvbt2_read_snr_reg(tnr_dmd->diver_sub, ®_value); ++ if (ret == CXD2880_RESULT_OK) { ++ ret = dvbt2_calc_snr(tnr_dmd->diver_sub, reg_value, snr_sub); ++ if (ret != CXD2880_RESULT_OK) ++ reg_value = 0; ++ } else if (ret == CXD2880_RESULT_ERROR_HW_STATE) { ++ reg_value = 0; ++ } else { ++ return ret; ++ } ++ ++ reg_value_sum += reg_value; ++ ++ ret = dvbt2_calc_snr(tnr_dmd, reg_value_sum, snr); ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_pre_ldpcber(struct cxd2880_tnrdmd ++ *tnr_dmd, u32 *ber) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ u32 bit_error = 0; ++ u32 period_exp = 0; ++ u32 n_ldpc = 0; ++ ++ if ((!tnr_dmd) || (!ber)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (slvt_freeze_reg(tnr_dmd) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0B) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ { ++ u8 data[5]; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x3C, data, ++ sizeof(data)) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (!(data[0] & 0x01)) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ ++ bit_error = ++ ((data[1] & 0x0F) << 24) | (data[2] << 16) | (data[3] << 8) ++ | data[4]; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xA0, data, ++ 1) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (((enum cxd2880_dvbt2_plp_fec)(data[0] & 0x03)) == ++ CXD2880_DVBT2_FEC_LDPC_16K) ++ n_ldpc = 16200; ++ else ++ n_ldpc = 64800; ++ ++ slvt_unfreeze_reg(tnr_dmd); ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x20) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x6F, data, ++ 1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ period_exp = data[0] & 0x0F; ++ } ++ ++ if (bit_error > ((1U << period_exp) * n_ldpc)) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ { ++ u32 div = 0; ++ u32 Q = 0; ++ u32 R = 0; ++ ++ if (period_exp >= 4) { ++ div = (1U << (period_exp - 4)) * (n_ldpc / 200); ++ ++ Q = (bit_error * 5) / div; ++ R = (bit_error * 5) % div; ++ ++ R *= 625; ++ Q = Q * 625 + R / div; ++ R = R % div; ++ } else { ++ div = (1U << period_exp) * (n_ldpc / 200); ++ ++ Q = (bit_error * 10) / div; ++ R = (bit_error * 10) % div; ++ ++ R *= 5000; ++ Q = Q * 5000 + R / div; ++ R = R % div; ++ } ++ ++ if (div / 2 <= R) ++ *ber = Q + 1; ++ else ++ *ber = Q; ++ } ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_post_bchfer(struct cxd2880_tnrdmd ++ *tnr_dmd, u32 *fer) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ u32 fec_error = 0; ++ u32 period = 0; ++ ++ if ((!tnr_dmd) || (!fer)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0B) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ { ++ u8 data[2]; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x1B, data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (!(data[0] & 0x80)) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ fec_error = ((data[0] & 0x7F) << 8) | (data[1]); ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x20) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x72, data, ++ 1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ period = (1 << (data[0] & 0x0F)); ++ } ++ ++ if ((period == 0) || (fec_error > period)) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ { ++ u32 div = 0; ++ u32 Q = 0; ++ u32 R = 0; ++ ++ div = period; ++ ++ Q = (fec_error * 1000) / div; ++ R = (fec_error * 1000) % div; ++ ++ R *= 1000; ++ Q = Q * 1000 + R / div; ++ R = R % div; ++ ++ if ((div != 1) && (div / 2 <= R)) ++ *fer = Q + 1; ++ else ++ *fer = Q; ++ } ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_pre_bchber(struct cxd2880_tnrdmd ++ *tnr_dmd, u32 *ber) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ u32 bit_error = 0; ++ u32 period_exp = 0; ++ u32 n_bch = 0; ++ ++ if ((!tnr_dmd) || (!ber)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ { ++ u8 data[3]; ++ enum cxd2880_dvbt2_plp_fec plp_fec_type = ++ CXD2880_DVBT2_FEC_LDPC_16K; ++ enum cxd2880_dvbt2_plp_code_rate plp_cr = CXD2880_DVBT2_R1_2; ++ ++ static const u16 n_bch_bits_lookup[2][8] = { ++ {7200, 9720, 10800, 11880, 12600, 13320, 5400, 6480}, ++ {32400, 38880, 43200, 48600, 51840, 54000, 21600, 25920} ++ }; ++ ++ if (slvt_freeze_reg(tnr_dmd) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0B) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x15, data, ++ 3) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (!(data[0] & 0x40)) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ ++ bit_error = ((data[0] & 0x3F) << 16) | (data[1] << 8) | data[2]; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x9D, data, ++ 1) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ plp_cr = (enum cxd2880_dvbt2_plp_code_rate)(data[0] & 0x07); ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xA0, data, ++ 1) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ plp_fec_type = (enum cxd2880_dvbt2_plp_fec)(data[0] & 0x03); ++ ++ slvt_unfreeze_reg(tnr_dmd); ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x20) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x72, data, ++ 1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ period_exp = data[0] & 0x0F; ++ ++ if ((plp_fec_type > CXD2880_DVBT2_FEC_LDPC_64K) || ++ (plp_cr > CXD2880_DVBT2_R2_5)) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ n_bch = n_bch_bits_lookup[plp_fec_type][plp_cr]; ++ } ++ ++ if (bit_error > ((1U << period_exp) * n_bch)) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ { ++ u32 div = 0; ++ u32 Q = 0; ++ u32 R = 0; ++ ++ if (period_exp >= 6) { ++ div = (1U << (period_exp - 6)) * (n_bch / 40); ++ ++ Q = (bit_error * 625) / div; ++ R = (bit_error * 625) % div; ++ ++ R *= 625; ++ Q = Q * 625 + R / div; ++ R = R % div; ++ } else { ++ div = (1U << period_exp) * (n_bch / 40); ++ ++ Q = (bit_error * 1000) / div; ++ R = (bit_error * 1000) % div; ++ ++ R *= 25000; ++ Q = Q * 25000 + R / div; ++ R = R % div; ++ } ++ ++ if (div / 2 <= R) ++ *ber = Q + 1; ++ else ++ *ber = Q; ++ } ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_packet_error_number(struct ++ cxd2880_tnrdmd ++ *tnr_dmd, ++ u32 *pen) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ u8 data[3]; ++ ++ if ((!tnr_dmd) || (!pen)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0B) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x39, data, ++ sizeof(data)) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (!(data[0] & 0x01)) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ *pen = ((data[1] << 8) | data[2]); ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_sampling_offset(struct cxd2880_tnrdmd ++ *tnr_dmd, int *ppm) ++{ ++ if ((!tnr_dmd) || (!ppm)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ { ++ u8 ctl_val_reg[5]; ++ u8 nominal_rate_reg[5]; ++ u32 trl_ctl_val = 0; ++ u32 trcg_nominal_rate = 0; ++ int num; ++ int den; ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ u8 sync_state = 0; ++ u8 ts_lock = 0; ++ u8 unlock_detected = 0; ++ s8 diff_upper = 0; ++ ++ if (slvt_freeze_reg(tnr_dmd) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ ret = ++ cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd, &sync_state, ++ &ts_lock, ++ &unlock_detected); ++ if (ret != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (sync_state != 6) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0B) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x34, ++ ctl_val_reg, ++ sizeof(ctl_val_reg)) != ++ CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x04) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x10, ++ nominal_rate_reg, ++ sizeof(nominal_rate_reg)) != ++ CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ slvt_unfreeze_reg(tnr_dmd); ++ ++ diff_upper = ++ (ctl_val_reg[0] & 0x7F) - (nominal_rate_reg[0] & 0x7F); ++ ++ if ((diff_upper < -1) || (diff_upper > 1)) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ trl_ctl_val = ctl_val_reg[1] << 24; ++ trl_ctl_val |= ctl_val_reg[2] << 16; ++ trl_ctl_val |= ctl_val_reg[3] << 8; ++ trl_ctl_val |= ctl_val_reg[4]; ++ ++ trcg_nominal_rate = nominal_rate_reg[1] << 24; ++ trcg_nominal_rate |= nominal_rate_reg[2] << 16; ++ trcg_nominal_rate |= nominal_rate_reg[3] << 8; ++ trcg_nominal_rate |= nominal_rate_reg[4]; ++ ++ trl_ctl_val >>= 1; ++ trcg_nominal_rate >>= 1; ++ ++ if (diff_upper == 1) ++ num = ++ (int)((trl_ctl_val + 0x80000000u) - ++ trcg_nominal_rate); ++ else if (diff_upper == -1) ++ num = ++ -(int)((trcg_nominal_rate + 0x80000000u) - ++ trl_ctl_val); ++ else ++ num = (int)(trl_ctl_val - trcg_nominal_rate); ++ ++ den = (nominal_rate_reg[0] & 0x7F) << 24; ++ den |= nominal_rate_reg[1] << 16; ++ den |= nominal_rate_reg[2] << 8; ++ den |= nominal_rate_reg[3]; ++ den = (den + (390625 / 2)) / 390625; ++ ++ den >>= 1; ++ ++ if (num >= 0) ++ *ppm = (num + (den / 2)) / den; ++ else ++ *ppm = (num - (den / 2)) / den; ++ } ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_sampling_offset_sub(struct ++ cxd2880_tnrdmd ++ *tnr_dmd, ++ int *ppm) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!ppm)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ ret = cxd2880_tnrdmd_dvbt2_mon_sampling_offset(tnr_dmd->diver_sub, ppm); ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_quality(struct cxd2880_tnrdmd ++ *tnr_dmd, u8 *quality) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ int snr = 0; ++ int snr_rel = 0; ++ u32 ber = 0; ++ u32 ber_sqi = 0; ++ enum cxd2880_dvbt2_plp_constell qam; ++ enum cxd2880_dvbt2_plp_code_rate code_rate; ++ ++ static const int snr_nordig_p1_db_1000[4][8] = { ++ {3500, 4700, 5600, 6600, 7200, 7700, 1300, 2200}, ++ {8700, 10100, 11400, 12500, 13300, 13800, 6000, 7200}, ++ {13000, 14800, 16200, 17700, 18700, 19400, 9800, 11100}, ++ {17000, 19400, 20800, 22900, 24300, 25100, 13200, 14800}, ++ }; ++ ++ if ((!tnr_dmd) || (!quality)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = cxd2880_tnrdmd_dvbt2_mon_pre_bchber(tnr_dmd, &ber); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ ret = cxd2880_tnrdmd_dvbt2_mon_snr(tnr_dmd, &snr); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ ret = ++ cxd2880_tnrdmd_dvbt2_mon_qam(tnr_dmd, CXD2880_DVBT2_PLP_DATA, &qam); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ ret = ++ cxd2880_tnrdmd_dvbt2_mon_code_rate(tnr_dmd, CXD2880_DVBT2_PLP_DATA, ++ &code_rate); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if ((code_rate > CXD2880_DVBT2_R2_5) || (qam > CXD2880_DVBT2_QAM256)) ++ return CXD2880_RESULT_ERROR_OTHER; ++ ++ if (ber > 100000) ++ ber_sqi = 0; ++ else if (ber >= 100) ++ ber_sqi = 6667; ++ else ++ ber_sqi = 16667; ++ ++ snr_rel = snr - snr_nordig_p1_db_1000[qam][code_rate]; ++ ++ if (snr_rel < -3000) { ++ *quality = 0; ++ } else if (snr_rel <= 3000) { ++ u32 temp_sqi = ++ (((snr_rel + 3000) * ber_sqi) + 500000) / 1000000; ++ *quality = (temp_sqi > 100) ? 100 : (u8)temp_sqi; ++ } else { ++ *quality = 100; ++ } ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_ts_rate(struct cxd2880_tnrdmd ++ *tnr_dmd, u32 *ts_rate_kbps) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ u32 rd_smooth_dp = 0; ++ u32 ep_ck_nume = 0; ++ u32 ep_ck_deno = 0; ++ u8 issy_on_data = 0; ++ ++ if ((!tnr_dmd) || (!ts_rate_kbps)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ { ++ u8 data[12]; ++ u8 sync_state = 0; ++ u8 ts_lock = 0; ++ u8 unlock_detected = 0; ++ ++ if (slvt_freeze_reg(tnr_dmd) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ ret = ++ cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd, &sync_state, ++ &ts_lock, ++ &unlock_detected); ++ if (ret != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (!ts_lock) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0B) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x23, data, ++ 12) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ rd_smooth_dp = (u32)((data[0] & 0x1F) << 24); ++ rd_smooth_dp |= (u32)(data[1] << 16); ++ rd_smooth_dp |= (u32)(data[2] << 8); ++ rd_smooth_dp |= (u32)data[3]; ++ ++ if (rd_smooth_dp < 214958) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ ++ ep_ck_nume = (u32)((data[4] & 0x3F) << 24); ++ ep_ck_nume |= (u32)(data[5] << 16); ++ ep_ck_nume |= (u32)(data[6] << 8); ++ ep_ck_nume |= (u32)data[7]; ++ ++ ep_ck_deno = (u32)((data[8] & 0x3F) << 24); ++ ep_ck_deno |= (u32)(data[9] << 16); ++ ep_ck_deno |= (u32)(data[10] << 8); ++ ep_ck_deno |= (u32)data[11]; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x41, data, ++ 1) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ issy_on_data = data[0] & 0x01; ++ ++ slvt_unfreeze_reg(tnr_dmd); ++ } ++ ++ if (issy_on_data) { ++ if ((ep_ck_deno == 0) || (ep_ck_nume == 0) || ++ (ep_ck_deno >= ep_ck_nume)) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ ++ { ++ u32 ick_x100; ++ u32 div = 0; ++ u32 Q = 0; ++ u32 R = 0; ++ ++ switch (tnr_dmd->clk_mode) { ++ case CXD2880_TNRDMD_CLOCKMODE_A: ++ ick_x100 = 8228; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_B: ++ ick_x100 = 9330; ++ break; ++ case CXD2880_TNRDMD_CLOCKMODE_C: ++ ick_x100 = 9600; ++ break; ++ default: ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ } ++ ++ div = rd_smooth_dp; ++ ++ Q = ick_x100 * 262144U / div; ++ R = ick_x100 * 262144U % div; ++ ++ R *= 5U; ++ Q = Q * 5 + R / div; ++ R = R % div; ++ ++ R *= 2U; ++ Q = Q * 2 + R / div; ++ R = R % div; ++ ++ if (div / 2 <= R) ++ *ts_rate_kbps = Q + 1; ++ else ++ *ts_rate_kbps = Q; ++ } ++ ++ if (issy_on_data) { ++ u32 diff = ep_ck_nume - ep_ck_deno; ++ ++ while (diff > 0x7FFF) { ++ diff >>= 1; ++ ep_ck_nume >>= 1; ++ } ++ ++ *ts_rate_kbps -= ++ (*ts_rate_kbps * diff + ep_ck_nume / 2) / ep_ck_nume; ++ } ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_per(struct cxd2880_tnrdmd *tnr_dmd, ++ u32 *per) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ u32 packet_error = 0; ++ u32 period = 0; ++ ++ if (!tnr_dmd || !per) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ { ++ u8 rdata[3]; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0B) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x18, rdata, ++ 3) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if ((rdata[0] & 0x01) == 0) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ packet_error = (rdata[1] << 8) | rdata[2]; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x24) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xDC, rdata, ++ 1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ period = 1U << (rdata[0] & 0x0F); ++ } ++ ++ if ((period == 0) || (packet_error > period)) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ { ++ u32 div = 0; ++ u32 Q = 0; ++ u32 R = 0; ++ ++ div = period; ++ ++ Q = (packet_error * 1000) / div; ++ R = (packet_error * 1000) % div; ++ ++ R *= 1000; ++ Q = Q * 1000 + R / div; ++ R = R % div; ++ ++ if ((div != 1) && (div / 2 <= R)) ++ *per = Q + 1; ++ else ++ *per = Q; ++ } ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_qam(struct cxd2880_tnrdmd *tnr_dmd, ++ enum cxd2880_dvbt2_plp_btype type, ++ enum cxd2880_dvbt2_plp_constell ++ *qam) ++{ ++ u8 data; ++ u8 l1_post_ok = 0; ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!qam)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (slvt_freeze_reg(tnr_dmd) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0B) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x86, &l1_post_ok, ++ 1) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (!(l1_post_ok & 0x01)) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ ++ if (type == CXD2880_DVBT2_PLP_COMMON) { ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xB6, &data, ++ 1) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (data == 0) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xB1, &data, ++ 1) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ } else { ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x9E, &data, ++ 1) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ } ++ ++ slvt_unfreeze_reg(tnr_dmd); ++ ++ *qam = (enum cxd2880_dvbt2_plp_constell)(data & 0x07); ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_code_rate(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum cxd2880_dvbt2_plp_btype ++ type, ++ enum ++ cxd2880_dvbt2_plp_code_rate ++ *code_rate) ++{ ++ u8 data; ++ u8 l1_post_ok = 0; ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!code_rate)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (slvt_freeze_reg(tnr_dmd) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0B) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x86, &l1_post_ok, ++ 1) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (!(l1_post_ok & 0x01)) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ ++ if (type == CXD2880_DVBT2_PLP_COMMON) { ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xB6, &data, ++ 1) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (data == 0) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xB0, &data, ++ 1) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ } else { ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x9D, &data, ++ 1) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ } ++ ++ slvt_unfreeze_reg(tnr_dmd); ++ ++ *code_rate = (enum cxd2880_dvbt2_plp_code_rate)(data & 0x07); ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_profile(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum cxd2880_dvbt2_profile ++ *profile) ++{ ++ if ((!tnr_dmd) || (!profile)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0B) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ { ++ u8 data; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x22, &data, ++ sizeof(data)) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (data & 0x02) { ++ if (data & 0x01) ++ *profile = CXD2880_DVBT2_PROFILE_LITE; ++ else ++ *profile = CXD2880_DVBT2_PROFILE_BASE; ++ } else { ++ enum cxd2880_ret ret = CXD2880_RESULT_ERROR_HW_STATE; ++ ++ if (tnr_dmd->diver_mode == ++ CXD2880_TNRDMD_DIVERMODE_MAIN) ++ ret = ++ cxd2880_tnrdmd_dvbt2_mon_profile( ++ tnr_dmd->diver_sub, profile); ++ ++ return ret; ++ } ++ } ++ ++ return CXD2880_RESULT_OK; ++} ++ ++static enum cxd2880_ret dvbt2_calc_sdi(struct cxd2880_tnrdmd *tnr_dmd, ++ int rf_lvl, u8 *ssi) ++{ ++ enum cxd2880_dvbt2_plp_constell qam; ++ enum cxd2880_dvbt2_plp_code_rate code_rate; ++ int prel; ++ int temp_ssi = 0; ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ static const int ref_dbm_1000[4][8] = { ++ {-96000, -95000, -94000, -93000, -92000, -92000, -98000, ++ -97000}, ++ {-91000, -89000, -88000, -87000, -86000, -86000, -93000, ++ -92000}, ++ {-86000, -85000, -83000, -82000, -81000, -80000, -89000, ++ -88000}, ++ {-82000, -80000, -78000, -76000, -75000, -74000, -86000, ++ -84000}, ++ }; ++ ++ if ((!tnr_dmd) || (!ssi)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ ret = ++ cxd2880_tnrdmd_dvbt2_mon_qam(tnr_dmd, CXD2880_DVBT2_PLP_DATA, &qam); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ ret = ++ cxd2880_tnrdmd_dvbt2_mon_code_rate(tnr_dmd, CXD2880_DVBT2_PLP_DATA, ++ &code_rate); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if ((code_rate > CXD2880_DVBT2_R2_5) || (qam > CXD2880_DVBT2_QAM256)) ++ return CXD2880_RESULT_ERROR_OTHER; ++ ++ prel = rf_lvl - ref_dbm_1000[qam][code_rate]; ++ ++ if (prel < -15000) ++ temp_ssi = 0; ++ else if (prel < 0) ++ temp_ssi = ((2 * (prel + 15000)) + 1500) / 3000; ++ else if (prel < 20000) ++ temp_ssi = (((4 * prel) + 500) / 1000) + 10; ++ else if (prel < 35000) ++ temp_ssi = (((2 * (prel - 20000)) + 1500) / 3000) + 90; ++ else ++ temp_ssi = 100; ++ ++ *ssi = (temp_ssi > 100) ? 100 : (u8)temp_ssi; ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_ssi(struct cxd2880_tnrdmd *tnr_dmd, ++ u8 *ssi) ++{ ++ int rf_lvl = 0; ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!ssi)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = cxd2880_tnrdmd_mon_rf_lvl(tnr_dmd, &rf_lvl); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ ret = dvbt2_calc_sdi(tnr_dmd, rf_lvl, ssi); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_ssi_sub(struct cxd2880_tnrdmd ++ *tnr_dmd, u8 *ssi) ++{ ++ int rf_lvl = 0; ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!ssi)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = cxd2880_tnrdmd_mon_rf_lvl(tnr_dmd->diver_sub, &rf_lvl); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ ret = dvbt2_calc_sdi(tnr_dmd, rf_lvl, ssi); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ return ret; ++} +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt2_mon.h b/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt2_mon.h +new file mode 100644 +index 0000000000000000000000000000000000000000..784ad2844d1b06af8594c25f1f6f6b67ded9dc71 +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt2_mon.h +@@ -0,0 +1,170 @@ ++/* ++ * cxd2880_tnrdmd_dvbt2_mon.h ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * DVB-T2 monitor interface ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#ifndef CXD2880_TNRDMD_DVBT2_MON_H ++#define CXD2880_TNRDMD_DVBT2_MON_H ++ ++#include "cxd2880_tnrdmd.h" ++#include "cxd2880_dvbt2.h" ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_sync_stat(struct cxd2880_tnrdmd ++ *tnr_dmd, u8 *sync_stat, ++ u8 *ts_lock_stat, ++ u8 *unlock_detected); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_sync_stat_sub(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ u8 *sync_stat, ++ u8 *unlock_detected); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_carrier_offset(struct cxd2880_tnrdmd ++ *tnr_dmd, int *offset); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_carrier_offset_sub(struct ++ cxd2880_tnrdmd ++ *tnr_dmd, ++ int *offset); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_l1_pre(struct cxd2880_tnrdmd *tnr_dmd, ++ struct cxd2880_dvbt2_l1pre ++ *l1_pre); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_version(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum cxd2880_dvbt2_version ++ *ver); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_ofdm(struct cxd2880_tnrdmd *tnr_dmd, ++ struct cxd2880_dvbt2_ofdm *ofdm); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_data_plps(struct cxd2880_tnrdmd ++ *tnr_dmd, u8 *plp_ids, ++ u8 *num_plps); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_active_plp(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum ++ cxd2880_dvbt2_plp_btype ++ type, ++ struct cxd2880_dvbt2_plp ++ *plp_info); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_data_plp_error(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ u8 *plp_error); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_l1_change(struct cxd2880_tnrdmd ++ *tnr_dmd, u8 *l1_change); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_l1_post(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ struct cxd2880_dvbt2_l1post ++ *l1_post); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_bbheader(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum cxd2880_dvbt2_plp_btype ++ type, ++ struct cxd2880_dvbt2_bbheader ++ *bbheader); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_in_bandb_ts_rate(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum ++ cxd2880_dvbt2_plp_btype ++ type, ++ u32 *ts_rate_bps); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_spectrum_sense(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum ++ cxd2880_tnrdmd_spectrum_sense ++ *sense); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_snr(struct cxd2880_tnrdmd *tnr_dmd, ++ int *snr); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_snr_diver(struct cxd2880_tnrdmd ++ *tnr_dmd, int *snr, ++ int *snr_main, ++ int *snr_sub); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_pre_ldpcber(struct cxd2880_tnrdmd ++ *tnr_dmd, u32 *ber); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_post_bchfer(struct cxd2880_tnrdmd ++ *tnr_dmd, u32 *fer); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_pre_bchber(struct cxd2880_tnrdmd ++ *tnr_dmd, u32 *ber); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_packet_error_number(struct ++ cxd2880_tnrdmd ++ *tnr_dmd, ++ u32 *pen); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_sampling_offset(struct cxd2880_tnrdmd ++ *tnr_dmd, int *ppm); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_sampling_offset_sub(struct ++ cxd2880_tnrdmd ++ *tnr_dmd, ++ int *ppm); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_ts_rate(struct cxd2880_tnrdmd ++ *tnr_dmd, u32 *ts_rate_kbps); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_quality(struct cxd2880_tnrdmd ++ *tnr_dmd, u8 *quality); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_per(struct cxd2880_tnrdmd *tnr_dmd, ++ u32 *per); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_qam(struct cxd2880_tnrdmd *tnr_dmd, ++ enum cxd2880_dvbt2_plp_btype type, ++ enum cxd2880_dvbt2_plp_constell ++ *qam); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_code_rate(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum cxd2880_dvbt2_plp_btype ++ type, ++ enum ++ cxd2880_dvbt2_plp_code_rate ++ *code_rate); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_profile(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum cxd2880_dvbt2_profile ++ *profile); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_ssi(struct cxd2880_tnrdmd *tnr_dmd, ++ u8 *ssi); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt2_mon_ssi_sub(struct cxd2880_tnrdmd ++ *tnr_dmd, u8 *ssi); ++ ++#endif +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt_mon.c b/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt_mon.c +new file mode 100644 +index 0000000000000000000000000000000000000000..d890081b6424b51ddce4fc770a8ed94af14e153e +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt_mon.c +@@ -0,0 +1,1190 @@ ++/* ++ * cxd2880_tnrdmd_dvbt_mon.c ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * DVB-T monitor functions ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#include "cxd2880_tnrdmd_mon.h" ++#include "cxd2880_tnrdmd_dvbt.h" ++#include "cxd2880_tnrdmd_dvbt_mon.h" ++#include "cxd2880_math.h" ++ ++static enum cxd2880_ret is_tps_locked(struct cxd2880_tnrdmd *tnr_dmd); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_sync_stat(struct cxd2880_tnrdmd ++ *tnr_dmd, u8 *sync_stat, ++ u8 *ts_lock_stat, ++ u8 *unlock_detected) ++{ ++ u8 rdata = 0x00; ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!sync_stat) || (!ts_lock_stat) || (!unlock_detected)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0D) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x10, &rdata, ++ 1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ *unlock_detected = (u8)((rdata & 0x10) ? 1 : 0); ++ *sync_stat = (u8)(rdata & 0x07); ++ *ts_lock_stat = (u8)((rdata & 0x20) ? 1 : 0); ++ ++ if (*sync_stat == 0x07) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_sync_stat_sub(struct cxd2880_tnrdmd ++ *tnr_dmd, u8 *sync_stat, ++ u8 *unlock_detected) ++{ ++ u8 ts_lock_stat = 0; ++ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!sync_stat) || (!unlock_detected)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ ret = ++ cxd2880_tnrdmd_dvbt_mon_sync_stat(tnr_dmd->diver_sub, sync_stat, ++ &ts_lock_stat, unlock_detected); ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_mode_guard(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum cxd2880_dvbt_mode ++ *mode, ++ enum cxd2880_dvbt_guard ++ *guard) ++{ ++ u8 rdata = 0x00; ++ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!mode) || (!guard)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (slvt_freeze_reg(tnr_dmd) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ ret = is_tps_locked(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) ++ ret = ++ cxd2880_tnrdmd_dvbt_mon_mode_guard( ++ tnr_dmd->diver_sub, mode, guard); ++ ++ return ret; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0D) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x1B, &rdata, ++ 1) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ slvt_unfreeze_reg(tnr_dmd); ++ ++ *mode = (enum cxd2880_dvbt_mode)((rdata >> 2) & 0x03); ++ *guard = (enum cxd2880_dvbt_guard)(rdata & 0x03); ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_carrier_offset(struct cxd2880_tnrdmd ++ *tnr_dmd, int *offset) ++{ ++ u8 rdata[4]; ++ u32 ctl_val = 0; ++ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!offset)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (slvt_freeze_reg(tnr_dmd) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ ret = is_tps_locked(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return ret; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0D) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x1D, rdata, ++ 4) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ slvt_unfreeze_reg(tnr_dmd); ++ ++ ctl_val = ++ ((rdata[0] & 0x1F) << 24) | (rdata[1] << 16) | (rdata[2] << 8) | ++ (rdata[3]); ++ *offset = cxd2880_convert2s_complement(ctl_val, 29); ++ *offset = -1 * ((*offset) * (u8)tnr_dmd->bandwidth / 235); ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_carrier_offset_sub(struct ++ cxd2880_tnrdmd ++ *tnr_dmd, ++ int *offset) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!offset)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ ret = ++ cxd2880_tnrdmd_dvbt_mon_carrier_offset(tnr_dmd->diver_sub, offset); ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_pre_viterbiber(struct cxd2880_tnrdmd ++ *tnr_dmd, u32 *ber) ++{ ++ u8 rdata[2]; ++ u32 bit_error = 0; ++ u32 period = 0; ++ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!ber)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (slvt_freeze_reg(tnr_dmd) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x10) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x39, rdata, ++ 1) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if ((rdata[0] & 0x01) == 0) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x22, rdata, ++ 2) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ bit_error = (rdata[0] << 8) | rdata[1]; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x6F, rdata, ++ 1) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ slvt_unfreeze_reg(tnr_dmd); ++ ++ period = ((rdata[0] & 0x07) == 0) ? 256 : (0x1000 << (rdata[0] & 0x07)); ++ ++ if ((period == 0) || (bit_error > period)) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ { ++ u32 div = 0; ++ u32 Q = 0; ++ u32 R = 0; ++ ++ div = period / 128; ++ ++ Q = (bit_error * 3125) / div; ++ R = (bit_error * 3125) % div; ++ ++ R *= 25; ++ Q = Q * 25 + R / div; ++ R = R % div; ++ ++ if (div / 2 <= R) ++ *ber = Q + 1; ++ else ++ *ber = Q; ++ } ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_pre_rsber(struct cxd2880_tnrdmd ++ *tnr_dmd, u32 *ber) ++{ ++ u8 rdata[3]; ++ u32 bit_error = 0; ++ u32 period_exp = 0; ++ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!ber)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0D) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x15, rdata, ++ 3) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if ((rdata[0] & 0x40) == 0) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ bit_error = ((rdata[0] & 0x3F) << 16) | (rdata[1] << 8) | rdata[2]; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x10) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x60, rdata, ++ 1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ period_exp = (rdata[0] & 0x1F); ++ ++ if ((period_exp <= 11) && (bit_error > (1U << period_exp) * 204 * 8)) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ { ++ u32 div = 0; ++ u32 Q = 0; ++ u32 R = 0; ++ ++ if (period_exp <= 8) ++ div = (1U << period_exp) * 51; ++ else ++ div = (1U << 8) * 51; ++ ++ Q = (bit_error * 250) / div; ++ R = (bit_error * 250) % div; ++ ++ R *= 1250; ++ Q = Q * 1250 + R / div; ++ R = R % div; ++ ++ if (period_exp > 8) { ++ *ber = ++ (Q + (1 << (period_exp - 9))) >> (period_exp - 8); ++ } else { ++ if (div / 2 <= R) ++ *ber = Q + 1; ++ else ++ *ber = Q; ++ } ++ } ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_tps_info(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ struct cxd2880_dvbt_tpsinfo ++ *info) ++{ ++ u8 rdata[7]; ++ u8 cell_id_ok = 0; ++ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!info)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (slvt_freeze_reg(tnr_dmd) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ ret = is_tps_locked(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) ++ ret = ++ cxd2880_tnrdmd_dvbt_mon_tps_info(tnr_dmd->diver_sub, ++ info); ++ ++ return ret; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0D) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x29, rdata, ++ 7) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x11) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0xD5, &cell_id_ok, ++ 1) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ slvt_unfreeze_reg(tnr_dmd); ++ ++ info->constellation = ++ (enum cxd2880_dvbt_constellation)((rdata[0] >> 6) & 0x03); ++ info->hierarchy = (enum cxd2880_dvbt_hierarchy)((rdata[0] >> 3) & 0x07); ++ info->rate_hp = (enum cxd2880_dvbt_coderate)(rdata[0] & 0x07); ++ info->rate_lp = (enum cxd2880_dvbt_coderate)((rdata[1] >> 5) & 0x07); ++ info->guard = (enum cxd2880_dvbt_guard)((rdata[1] >> 3) & 0x03); ++ info->mode = (enum cxd2880_dvbt_mode)((rdata[1] >> 1) & 0x03); ++ info->fnum = (rdata[2] >> 6) & 0x03; ++ info->length_indicator = rdata[2] & 0x3F; ++ info->cell_id = (u16)((rdata[3] << 8) | rdata[4]); ++ info->reserved_even = rdata[5] & 0x3F; ++ info->reserved_odd = rdata[6] & 0x3F; ++ ++ info->cell_id_ok = cell_id_ok & 0x01; ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_packet_error_number(struct ++ cxd2880_tnrdmd ++ *tnr_dmd, ++ u32 *pen) ++{ ++ u8 rdata[3]; ++ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!pen)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0D) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x26, rdata, ++ 3) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (!(rdata[0] & 0x01)) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ *pen = (rdata[1] << 8) | rdata[2]; ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_spectrum_sense(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum ++ cxd2880_tnrdmd_spectrum_sense ++ *sense) ++{ ++ u8 data = 0; ++ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!sense)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (slvt_freeze_reg(tnr_dmd) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ ret = is_tps_locked(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) ++ ret = ++ cxd2880_tnrdmd_dvbt_mon_spectrum_sense( ++ tnr_dmd->diver_sub, sense); ++ ++ return ret; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0D) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x1C, &data, ++ sizeof(data)) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ slvt_unfreeze_reg(tnr_dmd); ++ ++ *sense = ++ (data & 0x01) ? CXD2880_TNRDMD_SPECTRUM_INV : ++ CXD2880_TNRDMD_SPECTRUM_NORMAL; ++ ++ return ret; ++} ++ ++static enum cxd2880_ret dvbt_read_snr_reg(struct cxd2880_tnrdmd *tnr_dmd, ++ u16 *reg_value) ++{ ++ u8 rdata[2]; ++ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!reg_value)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (slvt_freeze_reg(tnr_dmd) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ ret = is_tps_locked(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return ret; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0D) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x13, rdata, ++ 2) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ slvt_unfreeze_reg(tnr_dmd); ++ ++ *reg_value = (rdata[0] << 8) | rdata[1]; ++ ++ return ret; ++} ++ ++static enum cxd2880_ret dvbt_calc_snr(struct cxd2880_tnrdmd *tnr_dmd, ++ u32 reg_value, int *snr) ++{ ++ if ((!tnr_dmd) || (!snr)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (reg_value == 0) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ if (reg_value > 4996) ++ reg_value = 4996; ++ ++ *snr = ++ 10 * 10 * ((int)cxd2880_math_log10(reg_value) - ++ (int)cxd2880_math_log10(5350 - reg_value)); ++ *snr += 28500; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_snr(struct cxd2880_tnrdmd *tnr_dmd, ++ int *snr) ++{ ++ u16 reg_value = 0; ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!snr)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ *snr = -1000 * 1000; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE) { ++ ret = dvbt_read_snr_reg(tnr_dmd, ®_value); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ ret = dvbt_calc_snr(tnr_dmd, reg_value, snr); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } else { ++ int snr_main = 0; ++ int snr_sub = 0; ++ ++ ret = ++ cxd2880_tnrdmd_dvbt_mon_snr_diver(tnr_dmd, snr, &snr_main, ++ &snr_sub); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_snr_diver(struct cxd2880_tnrdmd ++ *tnr_dmd, int *snr, ++ int *snr_main, int *snr_sub) ++{ ++ u16 reg_value = 0; ++ u32 reg_value_sum = 0; ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!snr) || (!snr_main) || (!snr_sub)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ *snr = -1000 * 1000; ++ *snr_main = -1000 * 1000; ++ *snr_sub = -1000 * 1000; ++ ++ if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = dvbt_read_snr_reg(tnr_dmd, ®_value); ++ if (ret == CXD2880_RESULT_OK) { ++ ret = dvbt_calc_snr(tnr_dmd, reg_value, snr_main); ++ if (ret != CXD2880_RESULT_OK) ++ reg_value = 0; ++ } else if (ret == CXD2880_RESULT_ERROR_HW_STATE) { ++ reg_value = 0; ++ } else { ++ return ret; ++ } ++ ++ reg_value_sum += reg_value; ++ ++ ret = dvbt_read_snr_reg(tnr_dmd->diver_sub, ®_value); ++ if (ret == CXD2880_RESULT_OK) { ++ ret = dvbt_calc_snr(tnr_dmd->diver_sub, reg_value, snr_sub); ++ if (ret != CXD2880_RESULT_OK) ++ reg_value = 0; ++ } else if (ret == CXD2880_RESULT_ERROR_HW_STATE) { ++ reg_value = 0; ++ } else { ++ return ret; ++ } ++ ++ reg_value_sum += reg_value; ++ ++ ret = dvbt_calc_snr(tnr_dmd, reg_value_sum, snr); ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_sampling_offset(struct cxd2880_tnrdmd ++ *tnr_dmd, int *ppm) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!ppm)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ { ++ u8 ctl_val_reg[5]; ++ u8 nominal_rate_reg[5]; ++ u32 trl_ctl_val = 0; ++ u32 trcg_nominal_rate = 0; ++ int num; ++ int den; ++ s8 diff_upper = 0; ++ ++ if (slvt_freeze_reg(tnr_dmd) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ ret = is_tps_locked(tnr_dmd); ++ if (ret != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return ret; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0D) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x21, ++ ctl_val_reg, ++ sizeof(ctl_val_reg)) != ++ CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x04) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x60, ++ nominal_rate_reg, ++ sizeof(nominal_rate_reg)) != ++ CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnr_dmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ slvt_unfreeze_reg(tnr_dmd); ++ ++ diff_upper = ++ (ctl_val_reg[0] & 0x7F) - (nominal_rate_reg[0] & 0x7F); ++ ++ if ((diff_upper < -1) || (diff_upper > 1)) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ trl_ctl_val = ctl_val_reg[1] << 24; ++ trl_ctl_val |= ctl_val_reg[2] << 16; ++ trl_ctl_val |= ctl_val_reg[3] << 8; ++ trl_ctl_val |= ctl_val_reg[4]; ++ ++ trcg_nominal_rate = nominal_rate_reg[1] << 24; ++ trcg_nominal_rate |= nominal_rate_reg[2] << 16; ++ trcg_nominal_rate |= nominal_rate_reg[3] << 8; ++ trcg_nominal_rate |= nominal_rate_reg[4]; ++ ++ trl_ctl_val >>= 1; ++ trcg_nominal_rate >>= 1; ++ ++ if (diff_upper == 1) ++ num = ++ (int)((trl_ctl_val + 0x80000000u) - ++ trcg_nominal_rate); ++ else if (diff_upper == -1) ++ num = ++ -(int)((trcg_nominal_rate + 0x80000000u) - ++ trl_ctl_val); ++ else ++ num = (int)(trl_ctl_val - trcg_nominal_rate); ++ ++ den = (nominal_rate_reg[0] & 0x7F) << 24; ++ den |= nominal_rate_reg[1] << 16; ++ den |= nominal_rate_reg[2] << 8; ++ den |= nominal_rate_reg[3]; ++ den = (den + (390625 / 2)) / 390625; ++ ++ den >>= 1; ++ ++ if (num >= 0) ++ *ppm = (num + (den / 2)) / den; ++ else ++ *ppm = (num - (den / 2)) / den; ++ } ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_sampling_offset_sub(struct ++ cxd2880_tnrdmd ++ *tnr_dmd, int *ppm) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!ppm)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ ret = cxd2880_tnrdmd_dvbt_mon_sampling_offset(tnr_dmd->diver_sub, ppm); ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_quality(struct cxd2880_tnrdmd *tnr_dmd, ++ u8 *quality) ++{ ++ struct cxd2880_dvbt_tpsinfo tps; ++ enum cxd2880_dvbt_profile profile = CXD2880_DVBT_PROFILE_HP; ++ u32 ber = 0; ++ int sn = 0; ++ int sn_rel = 0; ++ int ber_sqi = 0; ++ ++ static const int nordig_non_hdvbt_db_1000[3][5] = { ++ {5100, 6900, 7900, 8900, 9700}, ++ {10800, 13100, 14600, 15600, 16000}, ++ {16500, 18700, 20200, 21600, 22500} ++ }; ++ ++ static const int nordig_hier_hp_dvbt_db_1000[3][2][5] = { ++ { ++ {9100, 12000, 13600, 15000, 16600}, ++ {10900, 14100, 15700, 19400, 20600} ++ }, ++ { ++ {6800, 9100, 10400, 11900, 12700}, ++ {8500, 11000, 12800, 15000, 16000} ++ }, ++ { ++ {5800, 7900, 9100, 10300, 12100}, ++ {8000, 9300, 11600, 13000, 12900} ++ } ++ }; ++ ++ static const int nordig_hier_lp_dvbt_db_1000[3][2][5] = { ++ { ++ {12500, 14300, 15300, 16300, 16900}, ++ {16700, 19100, 20900, 22500, 23700} ++ }, ++ { ++ {15000, 17200, 18400, 19100, 20100}, ++ {18500, 21200, 23600, 24700, 25900} ++ }, ++ { ++ {19500, 21400, 22500, 23700, 24700}, ++ {21900, 24200, 25600, 26900, 27800} ++ } ++ }; ++ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!quality)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = cxd2880_tnrdmd_dvbt_mon_tps_info(tnr_dmd, &tps); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (tps.hierarchy != CXD2880_DVBT_HIERARCHY_NON) { ++ u8 data = 0; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x10) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x67, &data, ++ 1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ profile = ++ ((data & 0x01) == ++ 0x01) ? CXD2880_DVBT_PROFILE_LP : CXD2880_DVBT_PROFILE_HP; ++ } ++ ++ ret = cxd2880_tnrdmd_dvbt_mon_pre_rsber(tnr_dmd, &ber); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ ret = cxd2880_tnrdmd_dvbt_mon_snr(tnr_dmd, &sn); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if ((tps.constellation >= CXD2880_DVBT_CONSTELLATION_RESERVED_3) || ++ (tps.rate_hp >= CXD2880_DVBT_CODERATE_RESERVED_5) || ++ (tps.rate_lp >= CXD2880_DVBT_CODERATE_RESERVED_5) || ++ (tps.hierarchy > CXD2880_DVBT_HIERARCHY_4)) { ++ return CXD2880_RESULT_ERROR_OTHER; ++ } ++ ++ if ((tps.hierarchy != CXD2880_DVBT_HIERARCHY_NON) && ++ (tps.constellation == CXD2880_DVBT_CONSTELLATION_QPSK)) ++ return CXD2880_RESULT_ERROR_OTHER; ++ ++ if (tps.hierarchy == CXD2880_DVBT_HIERARCHY_NON) ++ sn_rel = ++ sn - ++ nordig_non_hdvbt_db_1000[tps.constellation][tps.rate_hp]; ++ else if (profile == CXD2880_DVBT_PROFILE_LP) ++ sn_rel = ++ sn - nordig_hier_lp_dvbt_db_1000[(int)tps.hierarchy - ++ 1][(int)tps.constellation - ++ 1][tps.rate_lp]; ++ else ++ sn_rel = ++ sn - nordig_hier_hp_dvbt_db_1000[(int)tps.hierarchy - ++ 1][(int)tps.constellation - ++ 1][tps.rate_hp]; ++ ++ if (ber > 10000) { ++ ber_sqi = 0; ++ } else if (ber > 1) { ++ ber_sqi = (int)(10 * cxd2880_math_log10(ber)); ++ ber_sqi = 20 * (7 * 1000 - (ber_sqi)) - 40 * 1000; ++ } else { ++ ber_sqi = 100 * 1000; ++ } ++ ++ if (sn_rel < -7 * 1000) { ++ *quality = 0; ++ } else if (sn_rel < 3 * 1000) { ++ int tmp_sqi = (((sn_rel - (3 * 1000)) / 10) + 1000); ++ *quality = ++ (u8)(((tmp_sqi * ber_sqi) + ++ (1000000 / 2)) / (1000000)) & 0xFF; ++ } else { ++ *quality = (u8)((ber_sqi + 500) / 1000); ++ } ++ ++ if (*quality > 100) ++ *quality = 100; ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_per(struct cxd2880_tnrdmd *tnr_dmd, ++ u32 *per) ++{ ++ u32 packet_error = 0; ++ u32 period = 0; ++ u8 rdata[3]; ++ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!per)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0D) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x18, rdata, ++ 3) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if ((rdata[0] & 0x01) == 0) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ packet_error = (rdata[1] << 8) | rdata[2]; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x10) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x5C, rdata, ++ 1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ period = 1U << (rdata[0] & 0x0F); ++ ++ if ((period == 0) || (packet_error > period)) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ { ++ u32 div = 0; ++ u32 Q = 0; ++ u32 R = 0; ++ ++ div = period; ++ ++ Q = (packet_error * 1000) / div; ++ R = (packet_error * 1000) % div; ++ ++ R *= 1000; ++ Q = Q * 1000 + R / div; ++ R = R % div; ++ ++ if ((div != 1) && (div / 2 <= R)) ++ *per = Q + 1; ++ else ++ *per = Q; ++ } ++ ++ return ret; ++} ++ ++static enum cxd2880_ret dvbt_calc_ssi(struct cxd2880_tnrdmd *tnr_dmd, ++ int rf_lvl, u8 *ssi) ++{ ++ struct cxd2880_dvbt_tpsinfo tps; ++ int prel; ++ int temp_ssi = 0; ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ static const int ref_dbm_1000[3][5] = { ++ {-93000, -91000, -90000, -89000, -88000}, ++ {-87000, -85000, -84000, -83000, -82000}, ++ {-82000, -80000, -78000, -77000, -76000}, ++ }; ++ ++ if ((!tnr_dmd) || (!ssi)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ ret = cxd2880_tnrdmd_dvbt_mon_tps_info(tnr_dmd, &tps); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if ((tps.constellation >= CXD2880_DVBT_CONSTELLATION_RESERVED_3) || ++ (tps.rate_hp >= CXD2880_DVBT_CODERATE_RESERVED_5)) ++ return CXD2880_RESULT_ERROR_OTHER; ++ ++ prel = rf_lvl - ref_dbm_1000[tps.constellation][tps.rate_hp]; ++ ++ if (prel < -15000) ++ temp_ssi = 0; ++ else if (prel < 0) ++ temp_ssi = ((2 * (prel + 15000)) + 1500) / 3000; ++ else if (prel < 20000) ++ temp_ssi = (((4 * prel) + 500) / 1000) + 10; ++ else if (prel < 35000) ++ temp_ssi = (((2 * (prel - 20000)) + 1500) / 3000) + 90; ++ else ++ temp_ssi = 100; ++ ++ *ssi = (temp_ssi > 100) ? 100 : (u8)temp_ssi; ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_ssi(struct cxd2880_tnrdmd *tnr_dmd, ++ u8 *ssi) ++{ ++ int rf_lvl = 0; ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!ssi)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = cxd2880_tnrdmd_mon_rf_lvl(tnr_dmd, &rf_lvl); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ ret = dvbt_calc_ssi(tnr_dmd, rf_lvl, ssi); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_ssi_sub(struct cxd2880_tnrdmd *tnr_dmd, ++ u8 *ssi) ++{ ++ int rf_lvl = 0; ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!ssi)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ ret = cxd2880_tnrdmd_mon_rf_lvl(tnr_dmd->diver_sub, &rf_lvl); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ ret = dvbt_calc_ssi(tnr_dmd, rf_lvl, ssi); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ return ret; ++} ++ ++static enum cxd2880_ret is_tps_locked(struct cxd2880_tnrdmd *tnr_dmd) ++{ ++ u8 sync = 0; ++ u8 tslock = 0; ++ u8 early_unlock = 0; ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if (!tnr_dmd) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ ret = ++ cxd2880_tnrdmd_dvbt_mon_sync_stat(tnr_dmd, &sync, &tslock, ++ &early_unlock); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ ++ if (sync != 6) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ return CXD2880_RESULT_OK; ++} +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt_mon.h b/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt_mon.h +new file mode 100644 +index 0000000000000000000000000000000000000000..486fc466272e762cd0f647296e2d818c8b28702c +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt_mon.h +@@ -0,0 +1,106 @@ ++/* ++ * cxd2880_tnrdmd_dvbt_mon.h ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * DVB-T monitor interface ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#ifndef CXD2880_TNRDMD_DVBT_MON_H ++#define CXD2880_TNRDMD_DVBT_MON_H ++ ++#include "cxd2880_tnrdmd.h" ++#include "cxd2880_dvbt.h" ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_sync_stat(struct cxd2880_tnrdmd ++ *tnr_dmd, u8 *sync_stat, ++ u8 *ts_lock_stat, ++ u8 *unlock_detected); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_sync_stat_sub(struct cxd2880_tnrdmd ++ *tnr_dmd, u8 *sync_stat, ++ u8 *unlock_detected); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_mode_guard(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum cxd2880_dvbt_mode ++ *mode, ++ enum cxd2880_dvbt_guard ++ *guard); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_carrier_offset(struct cxd2880_tnrdmd ++ *tnr_dmd, int *offset); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_carrier_offset_sub(struct ++ cxd2880_tnrdmd ++ *tnr_dmd, ++ int *offset); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_pre_viterbiber(struct cxd2880_tnrdmd ++ *tnr_dmd, u32 *ber); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_pre_rsber(struct cxd2880_tnrdmd ++ *tnr_dmd, u32 *ber); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_tps_info(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ struct cxd2880_dvbt_tpsinfo ++ *info); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_packet_error_number(struct ++ cxd2880_tnrdmd ++ *tnr_dmd, ++ u32 *pen); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_spectrum_sense(struct cxd2880_tnrdmd ++ *tnr_dmd, ++ enum ++ cxd2880_tnrdmd_spectrum_sense ++ *sense); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_snr(struct cxd2880_tnrdmd *tnr_dmd, ++ int *snr); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_snr_diver(struct cxd2880_tnrdmd ++ *tnr_dmd, int *snr, ++ int *snr_main, int *snr_sub); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_sampling_offset(struct cxd2880_tnrdmd ++ *tnr_dmd, int *ppm); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_sampling_offset_sub(struct ++ cxd2880_tnrdmd ++ *tnr_dmd, ++ int *ppm); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_quality(struct cxd2880_tnrdmd *tnr_dmd, ++ u8 *quality); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_per(struct cxd2880_tnrdmd *tnr_dmd, ++ u32 *per); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_ssi(struct cxd2880_tnrdmd *tnr_dmd, ++ u8 *ssi); ++ ++enum cxd2880_ret cxd2880_tnrdmd_dvbt_mon_ssi_sub(struct cxd2880_tnrdmd *tnr_dmd, ++ u8 *ssi); ++ ++#endif +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_mon.c b/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_mon.c +new file mode 100644 +index 0000000000000000000000000000000000000000..0ac5b9bf3be803d5ea99c1aca67052142cfabff1 +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_mon.c +@@ -0,0 +1,207 @@ ++/* ++ * cxd2880_tnrdmd_mon.c ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * common monitor functions ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#include "cxd2880_common.h" ++#include "cxd2880_tnrdmd_mon.h" ++ ++enum cxd2880_ret cxd2880_tnrdmd_mon_rf_lvl(struct cxd2880_tnrdmd *tnr_dmd, ++ int *rf_lvl_db) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!rf_lvl_db)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x10, ++ 0x01) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x10) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ { ++ u8 data[2] = { 0x80, 0x00 }; ++ ++ if (tnr_dmd->io->write_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x5B, data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ CXD2880_SLEEP_IN_MON(2, tnr_dmd); ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x1A) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ { ++ u8 data[2]; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x15, data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if ((data[0] != 0) || (data[1] != 0)) ++ return CXD2880_RESULT_ERROR_OTHER; ++ ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x11, data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ *rf_lvl_db = ++ cxd2880_convert2s_complement((data[0] << 3) | ++ ((data[1] & 0xE0) >> 5), 11); ++ } ++ ++ *rf_lvl_db *= 125; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x10, ++ 0x00) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnr_dmd->rf_lvl_cmpstn) { ++ ret = tnr_dmd->rf_lvl_cmpstn(tnr_dmd, rf_lvl_db); ++ if (ret != CXD2880_RESULT_OK) ++ return ret; ++ } ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_mon_rf_lvl_sub(struct cxd2880_tnrdmd *tnr_dmd, ++ int *rf_lvl_db) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!rf_lvl_db)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ ret = cxd2880_tnrdmd_mon_rf_lvl(tnr_dmd->diver_sub, rf_lvl_db); ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_mon_internal_cpu_status(struct cxd2880_tnrdmd ++ *tnr_dmd, u16 *status) ++{ ++ u8 data[2] = { 0 }; ++ ++ if ((!tnr_dmd) || (!status)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x00, ++ 0x1A) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_SYS, 0x15, data, ++ 2) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ *status = (u16)(((u16)data[0] << 8) | data[1]); ++ ++ return CXD2880_RESULT_OK; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_mon_internal_cpu_status_sub(struct ++ cxd2880_tnrdmd ++ *tnr_dmd, ++ u16 *status) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!status)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ ret = ++ cxd2880_tnrdmd_mon_internal_cpu_status(tnr_dmd->diver_sub, status); ++ ++ return ret; ++} ++ ++enum cxd2880_ret cxd2880_tnrdmd_mon_ts_buf_info(struct cxd2880_tnrdmd *tnr_dmd, ++ struct ++ cxd2880_tnrdmd_ts_buf_info ++ *info) ++{ ++ u8 data[3] = { 0 }; ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ ++ if ((!tnr_dmd) || (!info)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) && ++ (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnr_dmd->io->write_reg(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x00, ++ 0x0A) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ if (tnr_dmd->io->read_regs(tnr_dmd->io, ++ CXD2880_IO_TGT_DMD, 0x50, data, ++ 3) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ info->read_ready = (u8)((data[0] & 0x10) ? 0x01 : 0x00); ++ info->almost_full = (u8)((data[0] & 0x08) ? 0x01 : 0x00); ++ info->almost_empty = (u8)((data[0] & 0x04) ? 0x01 : 0x00); ++ info->overflow = (u8)((data[0] & 0x02) ? 0x01 : 0x00); ++ info->underflow = (u8)((data[0] & 0x01) ? 0x01 : 0x00); ++ ++ info->packet_num = (u16)(((u32)(data[1] & 0x07) << 8) | data[2]); ++ ++ return ret; ++} +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_mon.h b/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_mon.h +new file mode 100644 +index 0000000000000000000000000000000000000000..506bd559668ff39fb9ca14a3a423569df3239ad1 +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_mon.h +@@ -0,0 +1,52 @@ ++/* ++ * cxd2880_tnrdmd_mon.h ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * common monitor interface ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#ifndef CXD2880_TNRDMD_MON_H ++#define CXD2880_TNRDMD_MON_H ++ ++#include "cxd2880_common.h" ++#include "cxd2880_tnrdmd.h" ++ ++enum cxd2880_ret cxd2880_tnrdmd_mon_rf_lvl(struct cxd2880_tnrdmd *tnr_dmd, ++ int *rf_lvl_db); ++ ++enum cxd2880_ret cxd2880_tnrdmd_mon_rf_lvl_sub(struct cxd2880_tnrdmd *tnr_dmd, ++ int *rf_lvl_db); ++ ++enum cxd2880_ret cxd2880_tnrdmd_mon_internal_cpu_status(struct cxd2880_tnrdmd ++ *tnr_dmd, u16 *status); ++ ++enum cxd2880_ret cxd2880_tnrdmd_mon_internal_cpu_status_sub(struct ++ cxd2880_tnrdmd ++ *tnr_dmd, ++ u16 *status); ++ ++enum cxd2880_ret cxd2880_tnrdmd_mon_ts_buf_info(struct cxd2880_tnrdmd *tnr_dmd, ++ struct ++ cxd2880_tnrdmd_ts_buf_info ++ *info); ++ ++#endif +diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_top.c b/drivers/media/dvb-frontends/cxd2880/cxd2880_top.c +new file mode 100644 +index 0000000000000000000000000000000000000000..66d78fb93a13264f60f6e34904704644133ffd59 +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_top.c +@@ -0,0 +1,1550 @@ ++/* ++ * cxd2880_top.c ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#include ++ ++#include "dvb_frontend.h" ++ ++#include "cxd2880.h" ++#include "cxd2880_tnrdmd_mon.h" ++#include "cxd2880_tnrdmd_dvbt2_mon.h" ++#include "cxd2880_tnrdmd_dvbt_mon.h" ++#include "cxd2880_integ_dvbt2.h" ++#include "cxd2880_integ_dvbt.h" ++#include "cxd2880_devio_spi.h" ++#include "cxd2880_spi_device.h" ++#include "cxd2880_tnrdmd_driver_version.h" ++ ++struct cxd2880_priv { ++ struct cxd2880_tnrdmd tnrdmd; ++ struct spi_device *spi; ++ struct cxd2880_io regio; ++ struct cxd2880_spi_device spi_device; ++ struct cxd2880_spi cxd2880_spi; ++ struct cxd2880_dvbt_tune_param dvbt_tune_param; ++ struct cxd2880_dvbt2_tune_param dvbt2_tune_param; ++ struct mutex *spi_mutex; /* For SPI access exclusive control */ ++}; ++ ++/* ++ * return value conversion table ++ */ ++static int return_tbl[] = { ++ 0, /* CXD2880_RESULT_OK */ ++ -EINVAL, /* CXD2880_RESULT_ERROR_ARG*/ ++ -EIO, /* CXD2880_RESULT_ERROR_IO */ ++ -EPERM, /* CXD2880_RESULT_ERROR_SW_STATE */ ++ -EBUSY, /* CXD2880_RESULT_ERROR_HW_STATE */ ++ -ETIME, /* CXD2880_RESULT_ERROR_TIMEOUT */ ++ -EAGAIN, /* CXD2880_RESULT_ERROR_UNLOCK */ ++ -ERANGE, /* CXD2880_RESULT_ERROR_RANGE */ ++ -EOPNOTSUPP, /* CXD2880_RESULT_ERROR_NOSUPPORT */ ++ -ECANCELED, /* CXD2880_RESULT_ERROR_CANCEL */ ++ -EPERM, /* CXD2880_RESULT_ERROR_OTHER */ ++ -EOVERFLOW, /* CXD2880_RESULT_ERROR_OVERFLOW */ ++ 0, /* CXD2880_RESULT_OK_CONFIRM */ ++}; ++ ++static enum cxd2880_ret cxd2880_pre_bit_err_t( ++ struct cxd2880_tnrdmd *tnrdmd, u32 *pre_bit_err, ++ u32 *pre_bit_count) ++{ ++ u8 rdata[2]; ++ ++ if ((!tnrdmd) || (!pre_bit_err) || (!pre_bit_count)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnrdmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnrdmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnrdmd->sys != CXD2880_DTV_SYS_DVBT) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (slvt_freeze_reg(tnrdmd) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnrdmd->io->write_reg(tnrdmd->io, CXD2880_IO_TGT_DMD, ++ 0x00, 0x10) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnrdmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnrdmd->io->read_regs(tnrdmd->io, CXD2880_IO_TGT_DMD, ++ 0x39, rdata, 1) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnrdmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if ((rdata[0] & 0x01) == 0) { ++ slvt_unfreeze_reg(tnrdmd); ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ ++ if (tnrdmd->io->read_regs(tnrdmd->io, CXD2880_IO_TGT_DMD, ++ 0x22, rdata, 2) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnrdmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ *pre_bit_err = (rdata[0] << 8) | rdata[1]; ++ ++ if (tnrdmd->io->read_regs(tnrdmd->io, CXD2880_IO_TGT_DMD, ++ 0x6F, rdata, 1) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnrdmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ slvt_unfreeze_reg(tnrdmd); ++ ++ *pre_bit_count = ((rdata[0] & 0x07) == 0) ? ++ 256 : (0x1000 << (rdata[0] & 0x07)); ++ ++ return CXD2880_RESULT_OK; ++} ++ ++static enum cxd2880_ret cxd2880_pre_bit_err_t2( ++ struct cxd2880_tnrdmd *tnrdmd, u32 *pre_bit_err, ++ u32 *pre_bit_count) ++{ ++ u32 period_exp = 0; ++ u32 n_ldpc = 0; ++ u8 data[5]; ++ ++ if ((!tnrdmd) || (!pre_bit_err) || (!pre_bit_count)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnrdmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnrdmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnrdmd->sys != CXD2880_DTV_SYS_DVBT2) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (slvt_freeze_reg(tnrdmd) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnrdmd->io->write_reg(tnrdmd->io, CXD2880_IO_TGT_DMD, ++ 0x00, 0x0B) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnrdmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnrdmd->io->read_regs(tnrdmd->io, CXD2880_IO_TGT_DMD, ++ 0x3C, data, sizeof(data)) ++ != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnrdmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (!(data[0] & 0x01)) { ++ slvt_unfreeze_reg(tnrdmd); ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ *pre_bit_err = ++ ((data[1] & 0x0F) << 24) | (data[2] << 16) | (data[3] << 8) | data[4]; ++ ++ if (tnrdmd->io->read_regs(tnrdmd->io, CXD2880_IO_TGT_DMD, ++ 0xA0, data, 1) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnrdmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (((enum cxd2880_dvbt2_plp_fec)(data[0] & 0x03)) == ++ CXD2880_DVBT2_FEC_LDPC_16K) ++ n_ldpc = 16200; ++ else ++ n_ldpc = 64800; ++ slvt_unfreeze_reg(tnrdmd); ++ ++ if (tnrdmd->io->write_reg(tnrdmd->io, CXD2880_IO_TGT_DMD, ++ 0x00, 0x20) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnrdmd->io->read_regs(tnrdmd->io, CXD2880_IO_TGT_DMD, ++ 0x6F, data, 1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ period_exp = data[0] & 0x0F; ++ ++ *pre_bit_count = (1U << period_exp) * n_ldpc; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++static enum cxd2880_ret cxd2880_post_bit_err_t(struct cxd2880_tnrdmd *tnrdmd, ++ u32 *post_bit_err, ++ u32 *post_bit_count) ++{ ++ u8 rdata[3]; ++ u32 bit_error = 0; ++ u32 period_exp = 0; ++ ++ if ((!tnrdmd) || (!post_bit_err) || (!post_bit_count)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnrdmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnrdmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnrdmd->sys != CXD2880_DTV_SYS_DVBT) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnrdmd->io->write_reg(tnrdmd->io, CXD2880_IO_TGT_DMD, ++ 0x00, 0x0D) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnrdmd->io->read_regs(tnrdmd->io, CXD2880_IO_TGT_DMD, ++ 0x15, rdata, 3) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if ((rdata[0] & 0x40) == 0) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ *post_bit_err = ((rdata[0] & 0x3F) << 16) | (rdata[1] << 8) | rdata[2]; ++ ++ if (tnrdmd->io->write_reg(tnrdmd->io, CXD2880_IO_TGT_DMD, ++ 0x00, 0x10) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnrdmd->io->read_regs(tnrdmd->io, CXD2880_IO_TGT_DMD, ++ 0x60, rdata, 1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ period_exp = (rdata[0] & 0x1F); ++ ++ if ((period_exp <= 11) && (bit_error > (1U << period_exp) * 204 * 8)) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ if (period_exp == 11) ++ *post_bit_count = 3342336; ++ else ++ *post_bit_count = (1U << period_exp) * 204 * 81; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++static enum cxd2880_ret cxd2880_post_bit_err_t2(struct cxd2880_tnrdmd *tnrdmd, ++ u32 *post_bit_err, ++ u32 *post_bit_count) ++{ ++ u32 period_exp = 0; ++ u32 n_bch = 0; ++ ++ if ((!tnrdmd) || (!post_bit_err) || (!post_bit_count)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnrdmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnrdmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnrdmd->sys != CXD2880_DTV_SYS_DVBT2) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ { ++ u8 data[3]; ++ enum cxd2880_dvbt2_plp_fec plp_fec_type = ++ CXD2880_DVBT2_FEC_LDPC_16K; ++ enum cxd2880_dvbt2_plp_code_rate plp_code_rate = ++ CXD2880_DVBT2_R1_2; ++ ++ static const u16 n_bch_bits_lookup[2][8] = { ++ {7200, 9720, 10800, 11880, 12600, 13320, 5400, 6480}, ++ {32400, 38880, 43200, 48600, 51840, 54000, 21600, 25920} ++ }; ++ ++ if (slvt_freeze_reg(tnrdmd) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnrdmd->io->write_reg(tnrdmd->io, CXD2880_IO_TGT_DMD, ++ 0x00, 0x0B) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnrdmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (tnrdmd->io->read_regs(tnrdmd->io, CXD2880_IO_TGT_DMD, ++ 0x15, data, 3) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnrdmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ if (!(data[0] & 0x40)) { ++ slvt_unfreeze_reg(tnrdmd); ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ } ++ ++ *post_bit_err = ++ ((data[0] & 0x3F) << 16) | (data[1] << 8) | data[2]; ++ ++ if (tnrdmd->io->read_regs(tnrdmd->io, CXD2880_IO_TGT_DMD, ++ 0x9D, data, 1) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnrdmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ plp_code_rate = ++ (enum cxd2880_dvbt2_plp_code_rate)(data[0] & 0x07); ++ ++ if (tnrdmd->io->read_regs(tnrdmd->io, CXD2880_IO_TGT_DMD, ++ 0xA0, data, 1) != CXD2880_RESULT_OK) { ++ slvt_unfreeze_reg(tnrdmd); ++ return CXD2880_RESULT_ERROR_IO; ++ } ++ ++ plp_fec_type = (enum cxd2880_dvbt2_plp_fec)(data[0] & 0x03); ++ ++ slvt_unfreeze_reg(tnrdmd); ++ ++ if (tnrdmd->io->write_reg(tnrdmd->io, CXD2880_IO_TGT_DMD, ++ 0x00, 0x20) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnrdmd->io->read_regs(tnrdmd->io, CXD2880_IO_TGT_DMD, ++ 0x72, data, 1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ period_exp = data[0] & 0x0F; ++ ++ if ((plp_fec_type > CXD2880_DVBT2_FEC_LDPC_64K) || ++ (plp_code_rate > CXD2880_DVBT2_R2_5)) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ n_bch = n_bch_bits_lookup[plp_fec_type][plp_code_rate]; ++ } ++ ++ if (*post_bit_err > ((1U << period_exp) * n_bch)) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ *post_bit_count = (1U << period_exp) * n_bch; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++static enum cxd2880_ret cxd2880_read_block_err_t( ++ struct cxd2880_tnrdmd *tnrdmd, ++ u32 *block_err, ++ u32 *block_count) ++{ ++ u8 rdata[3]; ++ ++ if ((!tnrdmd) || (!block_err) || (!block_count)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnrdmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnrdmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnrdmd->sys != CXD2880_DTV_SYS_DVBT) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ if (tnrdmd->io->write_reg(tnrdmd->io, CXD2880_IO_TGT_DMD, ++ 0x00, 0x0D) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnrdmd->io->read_regs(tnrdmd->io, CXD2880_IO_TGT_DMD, ++ 0x18, rdata, 3) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if ((rdata[0] & 0x01) == 0) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ *block_err = (rdata[1] << 8) | rdata[2]; ++ ++ if (tnrdmd->io->write_reg(tnrdmd->io, CXD2880_IO_TGT_DMD, ++ 0x00, 0x10) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnrdmd->io->read_regs(tnrdmd->io, CXD2880_IO_TGT_DMD, ++ 0x5C, rdata, 1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ *block_count = 1U << (rdata[0] & 0x0F); ++ ++ if ((*block_count == 0) || (*block_err > *block_count)) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++static enum cxd2880_ret cxd2880_read_block_err_t2( ++ struct cxd2880_tnrdmd *tnrdmd, ++ u32 *block_err, ++ u32 *block_count) ++{ ++ if ((!tnrdmd) || (!block_err) || (!block_count)) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnrdmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) ++ return CXD2880_RESULT_ERROR_ARG; ++ ++ if (tnrdmd->state != CXD2880_TNRDMD_STATE_ACTIVE) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ if (tnrdmd->sys != CXD2880_DTV_SYS_DVBT2) ++ return CXD2880_RESULT_ERROR_SW_STATE; ++ ++ { ++ u8 rdata[3]; ++ ++ if (tnrdmd->io->write_reg(tnrdmd->io, CXD2880_IO_TGT_DMD, ++ 0x00, 0x0B) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnrdmd->io->read_regs(tnrdmd->io, CXD2880_IO_TGT_DMD, ++ 0x18, rdata, 3) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if ((rdata[0] & 0x01) == 0) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ *block_err = (rdata[1] << 8) | rdata[2]; ++ ++ if (tnrdmd->io->write_reg(tnrdmd->io, CXD2880_IO_TGT_DMD, ++ 0x00, 0x24) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ if (tnrdmd->io->read_regs(tnrdmd->io, CXD2880_IO_TGT_DMD, ++ 0xDC, rdata, 1) != CXD2880_RESULT_OK) ++ return CXD2880_RESULT_ERROR_IO; ++ ++ *block_count = 1U << (rdata[0] & 0x0F); ++ } ++ ++ if ((*block_count == 0) || (*block_err > *block_count)) ++ return CXD2880_RESULT_ERROR_HW_STATE; ++ ++ return CXD2880_RESULT_OK; ++} ++ ++static void cxd2880_release(struct dvb_frontend *fe) ++{ ++ struct cxd2880_priv *priv = NULL; ++ ++ if (!fe) { ++ pr_err("%s: invalid arg.\n", __func__); ++ return; ++ } ++ priv = (struct cxd2880_priv *)fe->demodulator_priv; ++ kfree(priv); ++} ++ ++static int cxd2880_init(struct dvb_frontend *fe) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ struct cxd2880_priv *priv = NULL; ++ struct cxd2880_tnrdmd_create_param create_param; ++ ++ if (!fe) { ++ pr_err("%s: invalid arg.\n", __func__); ++ return -EINVAL; ++ } ++ ++ priv = (struct cxd2880_priv *)fe->demodulator_priv; ++ ++ create_param.ts_output_if = CXD2880_TNRDMD_TSOUT_IF_SPI; ++ create_param.xtal_share_type = CXD2880_TNRDMD_XTAL_SHARE_NONE; ++ create_param.en_internal_ldo = 1; ++ create_param.xosc_cap = 18; ++ create_param.xosc_i = 8; ++ create_param.stationary_use = 1; ++ ++ mutex_lock(priv->spi_mutex); ++ if (priv->tnrdmd.io != &priv->regio) { ++ ret = cxd2880_tnrdmd_create(&priv->tnrdmd, ++ &priv->regio, &create_param); ++ if (ret != CXD2880_RESULT_OK) { ++ mutex_unlock(priv->spi_mutex); ++ dev_info(&priv->spi->dev, ++ "%s: cxd2880 tnrdmd create failed %d\n", ++ __func__, ret); ++ return return_tbl[ret]; ++ } ++ } ++ ret = cxd2880_integ_init(&priv->tnrdmd); ++ if (ret != CXD2880_RESULT_OK) { ++ mutex_unlock(priv->spi_mutex); ++ dev_err(&priv->spi->dev, "%s: cxd2880 integ init failed %d\n", ++ __func__, ret); ++ return return_tbl[ret]; ++ } ++ mutex_unlock(priv->spi_mutex); ++ ++ dev_dbg(&priv->spi->dev, "%s: OK.\n", __func__); ++ ++ return return_tbl[ret]; ++} ++ ++static int cxd2880_sleep(struct dvb_frontend *fe) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ struct cxd2880_priv *priv = NULL; ++ ++ if (!fe) { ++ pr_err("%s: inavlid arg\n", __func__); ++ return -EINVAL; ++ } ++ ++ priv = (struct cxd2880_priv *)fe->demodulator_priv; ++ ++ mutex_lock(priv->spi_mutex); ++ ret = cxd2880_tnrdmd_sleep(&priv->tnrdmd); ++ mutex_unlock(priv->spi_mutex); ++ ++ dev_dbg(&priv->spi->dev, "%s: tnrdmd_sleep ret %d\n", ++ __func__, ret); ++ ++ return return_tbl[ret]; ++} ++ ++static int cxd2880_read_signal_strength(struct dvb_frontend *fe, ++ u16 *strength) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ struct cxd2880_priv *priv = NULL; ++ struct dtv_frontend_properties *c = NULL; ++ int level = 0; ++ ++ if ((!fe) || (!strength)) { ++ pr_err("%s: inavlid arg\n", __func__); ++ return -EINVAL; ++ } ++ ++ priv = (struct cxd2880_priv *)fe->demodulator_priv; ++ c = &fe->dtv_property_cache; ++ ++ mutex_lock(priv->spi_mutex); ++ if ((c->delivery_system == SYS_DVBT) || ++ (c->delivery_system == SYS_DVBT2)) { ++ ret = cxd2880_tnrdmd_mon_rf_lvl(&priv->tnrdmd, &level); ++ } else { ++ dev_dbg(&priv->spi->dev, "%s: invalid system\n", __func__); ++ mutex_unlock(priv->spi_mutex); ++ return -EINVAL; ++ } ++ mutex_unlock(priv->spi_mutex); ++ ++ level /= 125; ++ /* -105dBm - -30dBm (-105000/125 = -840, -30000/125 = -240 */ ++ level = clamp(level, -840, -240); ++ /* scale value to 0x0000-0xFFFF */ ++ *strength = (u16)(((level + 840) * 0xFFFF) / (-240 + 840)); ++ ++ if (ret != CXD2880_RESULT_OK) ++ dev_dbg(&priv->spi->dev, "%s: ret = %d\n", __func__, ret); ++ ++ return return_tbl[ret]; ++} ++ ++static int cxd2880_read_snr(struct dvb_frontend *fe, u16 *snr) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ int snrvalue = 0; ++ struct cxd2880_priv *priv = NULL; ++ struct dtv_frontend_properties *c = NULL; ++ ++ if ((!fe) || (!snr)) { ++ pr_err("%s: inavlid arg\n", __func__); ++ return -EINVAL; ++ } ++ ++ priv = (struct cxd2880_priv *)fe->demodulator_priv; ++ c = &fe->dtv_property_cache; ++ ++ mutex_lock(priv->spi_mutex); ++ if (c->delivery_system == SYS_DVBT) { ++ ret = cxd2880_tnrdmd_dvbt_mon_snr(&priv->tnrdmd, ++ &snrvalue); ++ } else if (c->delivery_system == SYS_DVBT2) { ++ ret = cxd2880_tnrdmd_dvbt2_mon_snr(&priv->tnrdmd, ++ &snrvalue); ++ } else { ++ dev_err(&priv->spi->dev, "%s: invalid system\n", __func__); ++ mutex_unlock(priv->spi_mutex); ++ return -EINVAL; ++ } ++ mutex_unlock(priv->spi_mutex); ++ ++ if (snrvalue < 0) ++ snrvalue = 0; ++ *snr = (u16)snrvalue; ++ ++ if (ret != CXD2880_RESULT_OK) ++ dev_dbg(&priv->spi->dev, "%s: ret = %d\n", __func__, ret); ++ ++ return return_tbl[ret]; ++} ++ ++static int cxd2880_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ struct cxd2880_priv *priv = NULL; ++ struct dtv_frontend_properties *c = NULL; ++ ++ if ((!fe) || (!ucblocks)) { ++ pr_err("%s: inavlid arg\n", __func__); ++ return -EINVAL; ++ } ++ ++ priv = (struct cxd2880_priv *)fe->demodulator_priv; ++ c = &fe->dtv_property_cache; ++ ++ mutex_lock(priv->spi_mutex); ++ if (c->delivery_system == SYS_DVBT) { ++ ret = cxd2880_tnrdmd_dvbt_mon_packet_error_number( ++ &priv->tnrdmd, ++ ucblocks); ++ } else if (c->delivery_system == SYS_DVBT2) { ++ ret = cxd2880_tnrdmd_dvbt2_mon_packet_error_number( ++ &priv->tnrdmd, ++ ucblocks); ++ } else { ++ dev_err(&priv->spi->dev, "%s: invlaid system\n", __func__); ++ mutex_unlock(priv->spi_mutex); ++ return -EINVAL; ++ } ++ mutex_unlock(priv->spi_mutex); ++ ++ if (ret != CXD2880_RESULT_OK) ++ dev_dbg(&priv->spi->dev, "%s: ret = %d\n", __func__, ret); ++ ++ return return_tbl[ret]; ++} ++ ++static int cxd2880_read_ber(struct dvb_frontend *fe, u32 *ber) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ struct cxd2880_priv *priv = NULL; ++ struct dtv_frontend_properties *c = NULL; ++ ++ if ((!fe) || (!ber)) { ++ pr_err("%s: inavlid arg\n", __func__); ++ return -EINVAL; ++ } ++ ++ priv = (struct cxd2880_priv *)fe->demodulator_priv; ++ c = &fe->dtv_property_cache; ++ ++ mutex_lock(priv->spi_mutex); ++ if (c->delivery_system == SYS_DVBT) { ++ ret = cxd2880_tnrdmd_dvbt_mon_pre_rsber(&priv->tnrdmd, ++ ber); ++ /* x100 to change unit.(10^7 -> 10^9 */ ++ *ber *= 100; ++ } else if (c->delivery_system == SYS_DVBT2) { ++ ret = cxd2880_tnrdmd_dvbt2_mon_pre_bchber(&priv->tnrdmd, ++ ber); ++ } else { ++ dev_err(&priv->spi->dev, "%s: invlaid system\n", __func__); ++ mutex_unlock(priv->spi_mutex); ++ return -EINVAL; ++ } ++ mutex_unlock(priv->spi_mutex); ++ ++ if (ret != CXD2880_RESULT_OK) ++ dev_dbg(&priv->spi->dev, "%s: ret = %d\n", __func__, ret); ++ ++ return return_tbl[ret]; ++} ++ ++static int cxd2880_set_frontend(struct dvb_frontend *fe) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ struct dtv_frontend_properties *c; ++ struct cxd2880_priv *priv; ++ enum cxd2880_dtv_bandwidth bw = CXD2880_DTV_BW_1_7_MHZ; ++ ++ if (!fe) { ++ pr_err("%s: inavlid arg\n", __func__); ++ return -EINVAL; ++ } ++ ++ priv = (struct cxd2880_priv *)fe->demodulator_priv; ++ c = &fe->dtv_property_cache; ++ ++ switch (c->bandwidth_hz) { ++ case 1712000: ++ bw = CXD2880_DTV_BW_1_7_MHZ; ++ break; ++ case 5000000: ++ bw = CXD2880_DTV_BW_5_MHZ; ++ break; ++ case 6000000: ++ bw = CXD2880_DTV_BW_6_MHZ; ++ break; ++ case 7000000: ++ bw = CXD2880_DTV_BW_7_MHZ; ++ break; ++ case 8000000: ++ bw = CXD2880_DTV_BW_8_MHZ; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ dev_info(&priv->spi->dev, "%s: sys:%d freq:%d bw:%d\n", __func__, ++ c->delivery_system, c->frequency, bw); ++ mutex_lock(priv->spi_mutex); ++ if (c->delivery_system == SYS_DVBT) { ++ priv->tnrdmd.sys = CXD2880_DTV_SYS_DVBT; ++ priv->dvbt_tune_param.center_freq_khz = c->frequency / 1000; ++ priv->dvbt_tune_param.bandwidth = bw; ++ priv->dvbt_tune_param.profile = CXD2880_DVBT_PROFILE_HP; ++ ret = cxd2880_integ_dvbt_tune(&priv->tnrdmd, ++ &priv->dvbt_tune_param); ++ } else if (c->delivery_system == SYS_DVBT2) { ++ priv->tnrdmd.sys = CXD2880_DTV_SYS_DVBT2; ++ priv->dvbt2_tune_param.center_freq_khz = c->frequency / 1000; ++ priv->dvbt2_tune_param.bandwidth = bw; ++ priv->dvbt2_tune_param.data_plp_id = (u16)c->stream_id; ++ ret = cxd2880_integ_dvbt2_tune(&priv->tnrdmd, ++ &priv->dvbt2_tune_param); ++ } else { ++ dev_err(&priv->spi->dev, "%s: invalid system\n", __func__); ++ mutex_unlock(priv->spi_mutex); ++ return -EINVAL; ++ } ++ mutex_unlock(priv->spi_mutex); ++ dev_info(&priv->spi->dev, "%s: tune result %d\n", __func__, ret); ++ ++ return return_tbl[ret]; ++} ++ ++static int cxd2880_read_status(struct dvb_frontend *fe, ++ enum fe_status *status) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ u8 sync = 0; ++ u8 lock = 0; ++ u8 unlock = 0; ++ struct cxd2880_priv *priv = NULL; ++ struct dtv_frontend_properties *c = NULL; ++ ++ if ((!fe) || (!status)) { ++ pr_err("%s: invalid arg\n", __func__); ++ return -EINVAL; ++ } ++ ++ priv = (struct cxd2880_priv *)fe->demodulator_priv; ++ c = &fe->dtv_property_cache; ++ *status = 0; ++ ++ if (priv->tnrdmd.state == CXD2880_TNRDMD_STATE_ACTIVE) { ++ mutex_lock(priv->spi_mutex); ++ if (c->delivery_system == SYS_DVBT) { ++ ret = cxd2880_tnrdmd_dvbt_mon_sync_stat( ++ &priv->tnrdmd, ++ &sync, ++ &lock, ++ &unlock); ++ } else if (c->delivery_system == SYS_DVBT2) { ++ ret = cxd2880_tnrdmd_dvbt2_mon_sync_stat( ++ &priv->tnrdmd, ++ &sync, ++ &lock, ++ &unlock); ++ } else { ++ dev_err(&priv->spi->dev, ++ "%s: invlaid system", __func__); ++ mutex_unlock(priv->spi_mutex); ++ return -EINVAL; ++ } ++ ++ mutex_unlock(priv->spi_mutex); ++ if (ret != CXD2880_RESULT_OK) { ++ dev_err(&priv->spi->dev, "%s: failed. sys = %d\n", ++ __func__, priv->tnrdmd.sys); ++ return return_tbl[ret]; ++ } ++ ++ if (sync == 6) { ++ *status = FE_HAS_SIGNAL | ++ FE_HAS_CARRIER; ++ } ++ if (lock) ++ *status |= FE_HAS_VITERBI | ++ FE_HAS_SYNC | ++ FE_HAS_LOCK; ++ } ++ ++ dev_dbg(&priv->spi->dev, "%s: status %d result %d\n", __func__, ++ *status, ret); ++ ++ return return_tbl[CXD2880_RESULT_OK]; ++} ++ ++static int cxd2880_tune(struct dvb_frontend *fe, ++ bool retune, ++ unsigned int mode_flags, ++ unsigned int *delay, ++ enum fe_status *status) ++{ ++ int ret = 0; ++ ++ if ((!fe) || (!delay) || (!status)) { ++ pr_err("%s: invalid arg.", __func__); ++ return -EINVAL; ++ } ++ ++ if (retune) { ++ ret = cxd2880_set_frontend(fe); ++ if (ret) { ++ pr_err("%s: cxd2880_set_frontend failed %d\n", ++ __func__, ret); ++ return ret; ++ } ++ } ++ ++ *delay = HZ / 5; ++ ++ return cxd2880_read_status(fe, status); ++} ++ ++static int cxd2880_get_frontend_t(struct dvb_frontend *fe, ++ struct dtv_frontend_properties *c) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ int result = 0; ++ struct cxd2880_priv *priv = NULL; ++ enum cxd2880_dvbt_mode mode = CXD2880_DVBT_MODE_2K; ++ enum cxd2880_dvbt_guard guard = CXD2880_DVBT_GUARD_1_32; ++ struct cxd2880_dvbt_tpsinfo tps; ++ enum cxd2880_tnrdmd_spectrum_sense sense; ++ u16 snr = 0; ++ int strength = 0; ++ u32 pre_bit_err = 0, pre_bit_count = 0; ++ u32 post_bit_err = 0, post_bit_count = 0; ++ u32 block_err = 0, block_count = 0; ++ ++ if ((!fe) || (!c)) { ++ pr_err("%s: invalid arg\n", __func__); ++ return -EINVAL; ++ } ++ ++ priv = (struct cxd2880_priv *)fe->demodulator_priv; ++ ++ mutex_lock(priv->spi_mutex); ++ ret = cxd2880_tnrdmd_dvbt_mon_mode_guard(&priv->tnrdmd, ++ &mode, &guard); ++ mutex_unlock(priv->spi_mutex); ++ if (ret == CXD2880_RESULT_OK) { ++ switch (mode) { ++ case CXD2880_DVBT_MODE_2K: ++ c->transmission_mode = TRANSMISSION_MODE_2K; ++ break; ++ case CXD2880_DVBT_MODE_8K: ++ c->transmission_mode = TRANSMISSION_MODE_8K; ++ break; ++ default: ++ c->transmission_mode = TRANSMISSION_MODE_2K; ++ dev_err(&priv->spi->dev, "%s: get invalid mode %d\n", ++ __func__, mode); ++ break; ++ } ++ switch (guard) { ++ case CXD2880_DVBT_GUARD_1_32: ++ c->guard_interval = GUARD_INTERVAL_1_32; ++ break; ++ case CXD2880_DVBT_GUARD_1_16: ++ c->guard_interval = GUARD_INTERVAL_1_16; ++ break; ++ case CXD2880_DVBT_GUARD_1_8: ++ c->guard_interval = GUARD_INTERVAL_1_8; ++ break; ++ case CXD2880_DVBT_GUARD_1_4: ++ c->guard_interval = GUARD_INTERVAL_1_4; ++ break; ++ default: ++ c->guard_interval = GUARD_INTERVAL_1_32; ++ dev_err(&priv->spi->dev, "%s: get invalid guard %d\n", ++ __func__, guard); ++ break; ++ } ++ } else { ++ c->transmission_mode = TRANSMISSION_MODE_2K; ++ c->guard_interval = GUARD_INTERVAL_1_32; ++ dev_dbg(&priv->spi->dev, ++ "%s: ModeGuard err %d\n", __func__, ret); ++ } ++ ++ mutex_lock(priv->spi_mutex); ++ ret = cxd2880_tnrdmd_dvbt_mon_tps_info(&priv->tnrdmd, &tps); ++ mutex_unlock(priv->spi_mutex); ++ if (ret == CXD2880_RESULT_OK) { ++ switch (tps.hierarchy) { ++ case CXD2880_DVBT_HIERARCHY_NON: ++ c->hierarchy = HIERARCHY_NONE; ++ break; ++ case CXD2880_DVBT_HIERARCHY_1: ++ c->hierarchy = HIERARCHY_1; ++ break; ++ case CXD2880_DVBT_HIERARCHY_2: ++ c->hierarchy = HIERARCHY_2; ++ break; ++ case CXD2880_DVBT_HIERARCHY_4: ++ c->hierarchy = HIERARCHY_4; ++ break; ++ default: ++ c->hierarchy = HIERARCHY_NONE; ++ dev_err(&priv->spi->dev, ++ "%s: TPSInfo hierarchy invalid %d\n", ++ __func__, tps.hierarchy); ++ break; ++ } ++ ++ switch (tps.rate_hp) { ++ case CXD2880_DVBT_CODERATE_1_2: ++ c->code_rate_HP = FEC_1_2; ++ break; ++ case CXD2880_DVBT_CODERATE_2_3: ++ c->code_rate_HP = FEC_2_3; ++ break; ++ case CXD2880_DVBT_CODERATE_3_4: ++ c->code_rate_HP = FEC_3_4; ++ break; ++ case CXD2880_DVBT_CODERATE_5_6: ++ c->code_rate_HP = FEC_5_6; ++ break; ++ case CXD2880_DVBT_CODERATE_7_8: ++ c->code_rate_HP = FEC_7_8; ++ break; ++ default: ++ c->code_rate_HP = FEC_NONE; ++ dev_err(&priv->spi->dev, ++ "%s: TPSInfo rateHP invalid %d\n", ++ __func__, tps.rate_hp); ++ break; ++ } ++ switch (tps.rate_lp) { ++ case CXD2880_DVBT_CODERATE_1_2: ++ c->code_rate_LP = FEC_1_2; ++ break; ++ case CXD2880_DVBT_CODERATE_2_3: ++ c->code_rate_LP = FEC_2_3; ++ break; ++ case CXD2880_DVBT_CODERATE_3_4: ++ c->code_rate_LP = FEC_3_4; ++ break; ++ case CXD2880_DVBT_CODERATE_5_6: ++ c->code_rate_LP = FEC_5_6; ++ break; ++ case CXD2880_DVBT_CODERATE_7_8: ++ c->code_rate_LP = FEC_7_8; ++ break; ++ default: ++ c->code_rate_LP = FEC_NONE; ++ dev_err(&priv->spi->dev, ++ "%s: TPSInfo rateLP invalid %d\n", ++ __func__, tps.rate_lp); ++ break; ++ } ++ switch (tps.constellation) { ++ case CXD2880_DVBT_CONSTELLATION_QPSK: ++ c->modulation = QPSK; ++ break; ++ case CXD2880_DVBT_CONSTELLATION_16QAM: ++ c->modulation = QAM_16; ++ break; ++ case CXD2880_DVBT_CONSTELLATION_64QAM: ++ c->modulation = QAM_64; ++ break; ++ default: ++ c->modulation = QPSK; ++ dev_err(&priv->spi->dev, ++ "%s: TPSInfo constellation invalid %d\n", ++ __func__, tps.constellation); ++ break; ++ } ++ } else { ++ c->hierarchy = HIERARCHY_NONE; ++ c->code_rate_HP = FEC_NONE; ++ c->code_rate_LP = FEC_NONE; ++ c->modulation = QPSK; ++ dev_dbg(&priv->spi->dev, ++ "%s: TPS info err %d\n", __func__, ret); ++ } ++ ++ mutex_lock(priv->spi_mutex); ++ ret = cxd2880_tnrdmd_dvbt_mon_spectrum_sense(&priv->tnrdmd, &sense); ++ mutex_unlock(priv->spi_mutex); ++ if (ret == CXD2880_RESULT_OK) { ++ switch (sense) { ++ case CXD2880_TNRDMD_SPECTRUM_NORMAL: ++ c->inversion = INVERSION_OFF; ++ break; ++ case CXD2880_TNRDMD_SPECTRUM_INV: ++ c->inversion = INVERSION_ON; ++ break; ++ default: ++ c->inversion = INVERSION_OFF; ++ dev_err(&priv->spi->dev, ++ "%s: spectrum sense invalid %d\n", ++ __func__, sense); ++ break; ++ } ++ } else { ++ c->inversion = INVERSION_OFF; ++ dev_dbg(&priv->spi->dev, ++ "%s: spectrum_sense %d\n", __func__, ret); ++ } ++ ++ mutex_lock(priv->spi_mutex); ++ ret = cxd2880_tnrdmd_mon_rf_lvl(&priv->tnrdmd, &strength); ++ mutex_unlock(priv->spi_mutex); ++ if (ret == CXD2880_RESULT_OK) { ++ c->strength.len = 1; ++ c->strength.stat[0].scale = FE_SCALE_DECIBEL; ++ c->strength.stat[0].svalue = strength; ++ } else { ++ c->strength.len = 1; ++ c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; ++ dev_dbg(&priv->spi->dev, "%s: mon_rf_lvl %d\n", ++ __func__, result); ++ } ++ ++ result = cxd2880_read_snr(fe, &snr); ++ if (!result) { ++ c->cnr.len = 1; ++ c->cnr.stat[0].scale = FE_SCALE_DECIBEL; ++ c->cnr.stat[0].svalue = snr; ++ } else { ++ c->cnr.len = 1; ++ c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; ++ dev_dbg(&priv->spi->dev, "%s: read_snr %d\n", __func__, result); ++ } ++ ++ mutex_lock(priv->spi_mutex); ++ ret = cxd2880_pre_bit_err_t(&priv->tnrdmd, &pre_bit_err, ++ &pre_bit_count); ++ mutex_unlock(priv->spi_mutex); ++ if (ret == CXD2880_RESULT_OK) { ++ c->pre_bit_error.len = 1; ++ c->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER; ++ c->pre_bit_error.stat[0].uvalue = pre_bit_err; ++ c->pre_bit_count.len = 1; ++ c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER; ++ c->pre_bit_count.stat[0].uvalue = pre_bit_count; ++ } else { ++ c->pre_bit_error.len = 1; ++ c->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; ++ c->pre_bit_count.len = 1; ++ c->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; ++ dev_dbg(&priv->spi->dev, ++ "%s: pre_bit_error_t failed %d\n", ++ __func__, ret); ++ } ++ ++ mutex_lock(priv->spi_mutex); ++ ret = cxd2880_post_bit_err_t(&priv->tnrdmd, ++ &post_bit_err, &post_bit_count); ++ mutex_unlock(priv->spi_mutex); ++ if (ret == CXD2880_RESULT_OK) { ++ c->post_bit_error.len = 1; ++ c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; ++ c->post_bit_error.stat[0].uvalue = post_bit_err; ++ c->post_bit_count.len = 1; ++ c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; ++ c->post_bit_count.stat[0].uvalue = post_bit_count; ++ } else { ++ c->post_bit_error.len = 1; ++ c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; ++ c->post_bit_count.len = 1; ++ c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; ++ dev_dbg(&priv->spi->dev, ++ "%s: post_bit_err_t %d\n", __func__, ret); ++ } ++ ++ mutex_lock(priv->spi_mutex); ++ ret = cxd2880_read_block_err_t(&priv->tnrdmd, ++ &block_err, &block_count); ++ mutex_unlock(priv->spi_mutex); ++ if (ret == CXD2880_RESULT_OK) { ++ c->block_error.len = 1; ++ c->block_error.stat[0].scale = FE_SCALE_COUNTER; ++ c->block_error.stat[0].uvalue = block_err; ++ c->block_count.len = 1; ++ c->block_count.stat[0].scale = FE_SCALE_COUNTER; ++ c->block_count.stat[0].uvalue = block_count; ++ } else { ++ c->block_error.len = 1; ++ c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; ++ c->block_count.len = 1; ++ c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; ++ dev_dbg(&priv->spi->dev, ++ "%s: read_block_err_t %d\n", __func__, ret); ++ } ++ ++ return 0; ++} ++ ++static int cxd2880_get_frontend_t2(struct dvb_frontend *fe, ++ struct dtv_frontend_properties *c) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ int result = 0; ++ struct cxd2880_priv *priv = NULL; ++ struct cxd2880_dvbt2_l1pre l1pre; ++ enum cxd2880_dvbt2_plp_code_rate coderate; ++ enum cxd2880_dvbt2_plp_constell qam; ++ enum cxd2880_tnrdmd_spectrum_sense sense; ++ u16 snr = 0; ++ int strength = 0; ++ u32 pre_bit_err = 0, pre_bit_count = 0; ++ u32 post_bit_err = 0, post_bit_count = 0; ++ u32 block_err = 0, block_count = 0; ++ ++ if ((!fe) || (!c)) { ++ pr_err("%s: invalid arg.\n", __func__); ++ return -EINVAL; ++ } ++ ++ priv = (struct cxd2880_priv *)fe->demodulator_priv; ++ ++ mutex_lock(priv->spi_mutex); ++ ret = cxd2880_tnrdmd_dvbt2_mon_l1_pre(&priv->tnrdmd, &l1pre); ++ mutex_unlock(priv->spi_mutex); ++ if (ret == CXD2880_RESULT_OK) { ++ switch (l1pre.fft_mode) { ++ case CXD2880_DVBT2_M2K: ++ c->transmission_mode = TRANSMISSION_MODE_2K; ++ break; ++ case CXD2880_DVBT2_M8K: ++ c->transmission_mode = TRANSMISSION_MODE_8K; ++ break; ++ case CXD2880_DVBT2_M4K: ++ c->transmission_mode = TRANSMISSION_MODE_4K; ++ break; ++ case CXD2880_DVBT2_M1K: ++ c->transmission_mode = TRANSMISSION_MODE_1K; ++ break; ++ case CXD2880_DVBT2_M16K: ++ c->transmission_mode = TRANSMISSION_MODE_16K; ++ break; ++ case CXD2880_DVBT2_M32K: ++ c->transmission_mode = TRANSMISSION_MODE_32K; ++ break; ++ default: ++ c->transmission_mode = TRANSMISSION_MODE_2K; ++ dev_err(&priv->spi->dev, ++ "%s: L1Pre fft_mode invalid %d\n", ++ __func__, l1pre.fft_mode); ++ break; ++ } ++ switch (l1pre.gi) { ++ case CXD2880_DVBT2_G1_32: ++ c->guard_interval = GUARD_INTERVAL_1_32; ++ break; ++ case CXD2880_DVBT2_G1_16: ++ c->guard_interval = GUARD_INTERVAL_1_16; ++ break; ++ case CXD2880_DVBT2_G1_8: ++ c->guard_interval = GUARD_INTERVAL_1_8; ++ break; ++ case CXD2880_DVBT2_G1_4: ++ c->guard_interval = GUARD_INTERVAL_1_4; ++ break; ++ case CXD2880_DVBT2_G1_128: ++ c->guard_interval = GUARD_INTERVAL_1_128; ++ break; ++ case CXD2880_DVBT2_G19_128: ++ c->guard_interval = GUARD_INTERVAL_19_128; ++ break; ++ case CXD2880_DVBT2_G19_256: ++ c->guard_interval = GUARD_INTERVAL_19_256; ++ break; ++ default: ++ c->guard_interval = GUARD_INTERVAL_1_32; ++ dev_err(&priv->spi->dev, ++ "%s: L1Pre gi invalid %d\n", ++ __func__, l1pre.gi); ++ break; ++ } ++ } else { ++ c->transmission_mode = TRANSMISSION_MODE_2K; ++ c->guard_interval = GUARD_INTERVAL_1_32; ++ dev_dbg(&priv->spi->dev, ++ "%s: L1Pre err %d\n", __func__, ret); ++ } ++ ++ mutex_lock(priv->spi_mutex); ++ ret = cxd2880_tnrdmd_dvbt2_mon_code_rate(&priv->tnrdmd, ++ CXD2880_DVBT2_PLP_DATA, ++ &coderate); ++ mutex_unlock(priv->spi_mutex); ++ if (ret == CXD2880_RESULT_OK) { ++ switch (coderate) { ++ case CXD2880_DVBT2_R1_2: ++ c->fec_inner = FEC_1_2; ++ break; ++ case CXD2880_DVBT2_R3_5: ++ c->fec_inner = FEC_3_5; ++ break; ++ case CXD2880_DVBT2_R2_3: ++ c->fec_inner = FEC_2_3; ++ break; ++ case CXD2880_DVBT2_R3_4: ++ c->fec_inner = FEC_3_4; ++ break; ++ case CXD2880_DVBT2_R4_5: ++ c->fec_inner = FEC_4_5; ++ break; ++ case CXD2880_DVBT2_R5_6: ++ c->fec_inner = FEC_5_6; ++ break; ++ default: ++ c->fec_inner = FEC_NONE; ++ dev_err(&priv->spi->dev, ++ "%s: CodeRate invalid %d\n", ++ __func__, coderate); ++ break; ++ } ++ } else { ++ c->fec_inner = FEC_NONE; ++ dev_dbg(&priv->spi->dev, "%s: CodeRate %d\n", __func__, ret); ++ } ++ ++ mutex_lock(priv->spi_mutex); ++ ret = cxd2880_tnrdmd_dvbt2_mon_qam(&priv->tnrdmd, ++ CXD2880_DVBT2_PLP_DATA, ++ &qam); ++ mutex_unlock(priv->spi_mutex); ++ if (ret == CXD2880_RESULT_OK) { ++ switch (qam) { ++ case CXD2880_DVBT2_QPSK: ++ c->modulation = QPSK; ++ break; ++ case CXD2880_DVBT2_QAM16: ++ c->modulation = QAM_16; ++ break; ++ case CXD2880_DVBT2_QAM64: ++ c->modulation = QAM_64; ++ break; ++ case CXD2880_DVBT2_QAM256: ++ c->modulation = QAM_256; ++ break; ++ default: ++ c->modulation = QPSK; ++ dev_err(&priv->spi->dev, ++ "%s: QAM invalid %d\n", ++ __func__, qam); ++ break; ++ } ++ } else { ++ c->modulation = QPSK; ++ dev_dbg(&priv->spi->dev, "%s: QAM %d\n", __func__, ret); ++ } ++ ++ mutex_lock(priv->spi_mutex); ++ ret = cxd2880_tnrdmd_dvbt2_mon_spectrum_sense(&priv->tnrdmd, &sense); ++ mutex_unlock(priv->spi_mutex); ++ if (ret == CXD2880_RESULT_OK) { ++ switch (sense) { ++ case CXD2880_TNRDMD_SPECTRUM_NORMAL: ++ c->inversion = INVERSION_OFF; ++ break; ++ case CXD2880_TNRDMD_SPECTRUM_INV: ++ c->inversion = INVERSION_ON; ++ break; ++ default: ++ c->inversion = INVERSION_OFF; ++ dev_err(&priv->spi->dev, ++ "%s: spectrum sense invalid %d\n", ++ __func__, sense); ++ break; ++ } ++ } else { ++ c->inversion = INVERSION_OFF; ++ dev_dbg(&priv->spi->dev, ++ "%s: SpectrumSense %d\n", __func__, ret); ++ } ++ ++ mutex_lock(priv->spi_mutex); ++ ret = cxd2880_tnrdmd_mon_rf_lvl(&priv->tnrdmd, &strength); ++ mutex_unlock(priv->spi_mutex); ++ if (ret == CXD2880_RESULT_OK) { ++ c->strength.len = 1; ++ c->strength.stat[0].scale = FE_SCALE_DECIBEL; ++ c->strength.stat[0].svalue = strength; ++ } else { ++ c->strength.len = 1; ++ c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; ++ dev_dbg(&priv->spi->dev, ++ "%s: mon_rf_lvl %d\n", __func__, ret); ++ } ++ ++ result = cxd2880_read_snr(fe, &snr); ++ if (!result) { ++ c->cnr.len = 1; ++ c->cnr.stat[0].scale = FE_SCALE_DECIBEL; ++ c->cnr.stat[0].svalue = snr; ++ } else { ++ c->cnr.len = 1; ++ c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; ++ dev_dbg(&priv->spi->dev, "%s: read_snr %d\n", __func__, result); ++ } ++ ++ mutex_lock(priv->spi_mutex); ++ ret = cxd2880_pre_bit_err_t2(&priv->tnrdmd, ++ &pre_bit_err, ++ &pre_bit_count); ++ mutex_unlock(priv->spi_mutex); ++ if (ret == CXD2880_RESULT_OK) { ++ c->pre_bit_error.len = 1; ++ c->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER; ++ c->pre_bit_error.stat[0].uvalue = pre_bit_err; ++ c->pre_bit_count.len = 1; ++ c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER; ++ c->pre_bit_count.stat[0].uvalue = pre_bit_count; ++ } else { ++ c->pre_bit_error.len = 1; ++ c->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; ++ c->pre_bit_count.len = 1; ++ c->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; ++ dev_dbg(&priv->spi->dev, ++ "%s: read_bit_err_t2 %d\n", __func__, ret); ++ } ++ ++ mutex_lock(priv->spi_mutex); ++ ret = cxd2880_post_bit_err_t2(&priv->tnrdmd, ++ &post_bit_err, &post_bit_count); ++ mutex_unlock(priv->spi_mutex); ++ if (ret == CXD2880_RESULT_OK) { ++ c->post_bit_error.len = 1; ++ c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; ++ c->post_bit_error.stat[0].uvalue = post_bit_err; ++ c->post_bit_count.len = 1; ++ c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; ++ c->post_bit_count.stat[0].uvalue = post_bit_count; ++ } else { ++ c->post_bit_error.len = 1; ++ c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; ++ c->post_bit_count.len = 1; ++ c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; ++ dev_dbg(&priv->spi->dev, ++ "%s: post_bit_err_t2 %d\n", __func__, ret); ++ } ++ ++ mutex_lock(priv->spi_mutex); ++ ret = cxd2880_read_block_err_t2(&priv->tnrdmd, ++ &block_err, &block_count); ++ mutex_unlock(priv->spi_mutex); ++ if (ret == CXD2880_RESULT_OK) { ++ c->block_error.len = 1; ++ c->block_error.stat[0].scale = FE_SCALE_COUNTER; ++ c->block_error.stat[0].uvalue = block_err; ++ c->block_count.len = 1; ++ c->block_count.stat[0].scale = FE_SCALE_COUNTER; ++ c->block_count.stat[0].uvalue = block_count; ++ } else { ++ c->block_error.len = 1; ++ c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; ++ c->block_count.len = 1; ++ c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; ++ dev_dbg(&priv->spi->dev, ++ "%s: read_block_err_t2 %d\n", __func__, ret); ++ } ++ ++ return 0; ++} ++ ++static int cxd2880_get_frontend(struct dvb_frontend *fe, ++ struct dtv_frontend_properties *props) ++{ ++ struct cxd2880_priv *priv = NULL; ++ int result = 0; ++ ++ if ((!fe) || (!props)) { ++ pr_err("%s: invalid arg.", __func__); ++ return -EINVAL; ++ } ++ ++ priv = (struct cxd2880_priv *)fe->demodulator_priv; ++ ++ dev_dbg(&priv->spi->dev, "%s: system=%d\n", __func__, ++ fe->dtv_property_cache.delivery_system); ++ switch (fe->dtv_property_cache.delivery_system) { ++ case SYS_DVBT: ++ result = cxd2880_get_frontend_t(fe, props); ++ break; ++ case SYS_DVBT2: ++ result = cxd2880_get_frontend_t2(fe, props); ++ break; ++ default: ++ result = -EINVAL; ++ break; ++ } ++ ++ return result; ++} ++ ++static enum dvbfe_algo cxd2880_get_frontend_algo(struct dvb_frontend *fe) ++{ ++ return DVBFE_ALGO_HW; ++} ++ ++static struct dvb_frontend_ops cxd2880_dvbt_t2_ops; ++ ++struct dvb_frontend *cxd2880_attach(struct dvb_frontend *fe, ++ struct cxd2880_config *cfg) ++{ ++ enum cxd2880_ret ret = CXD2880_RESULT_OK; ++ enum cxd2880_tnrdmd_chip_id chipid = ++ CXD2880_TNRDMD_CHIP_ID_UNKNOWN; ++ static struct cxd2880_priv *priv; ++ u8 data = 0; ++ ++ if (!fe) { ++ pr_err("%s: invalid arg.\n", __func__); ++ return NULL; ++ } ++ ++ priv = kzalloc(sizeof(struct cxd2880_priv), GFP_KERNEL); ++ if (!priv) ++ return NULL; ++ ++ priv->spi = cfg->spi; ++ priv->spi_mutex = cfg->spi_mutex; ++ priv->spi_device.spi = cfg->spi; ++ ++ memcpy(&fe->ops, &cxd2880_dvbt_t2_ops, ++ sizeof(struct dvb_frontend_ops)); ++ ++ ret = cxd2880_spi_device_initialize(&priv->spi_device, ++ CXD2880_SPI_MODE_0, ++ 55000000); ++ if (ret != CXD2880_RESULT_OK) { ++ dev_err(&priv->spi->dev, ++ "%s: spi_device_initialize failed. %d\n", ++ __func__, ret); ++ kfree(priv); ++ return NULL; ++ } ++ ++ ret = cxd2880_spi_device_create_spi(&priv->cxd2880_spi, ++ &priv->spi_device); ++ if (ret != CXD2880_RESULT_OK) { ++ dev_err(&priv->spi->dev, ++ "%s: spi_device_create_spi failed. %d\n", ++ __func__, ret); ++ kfree(priv); ++ return NULL; ++ } ++ ++ ret = cxd2880_io_spi_create(&priv->regio, &priv->cxd2880_spi, 0); ++ if (ret != CXD2880_RESULT_OK) { ++ dev_err(&priv->spi->dev, ++ "%s: io_spi_create failed. %d\n", __func__, ret); ++ kfree(priv); ++ return NULL; ++ } ++ if (priv->regio.write_reg(&priv->regio, CXD2880_IO_TGT_SYS, 0x00, 0x00) ++ != CXD2880_RESULT_OK) { ++ dev_err(&priv->spi->dev, ++ "%s: set bank to 0x00 failed.\n", __func__); ++ kfree(priv); ++ return NULL; ++ } ++ if (priv->regio.read_regs(&priv->regio, ++ CXD2880_IO_TGT_SYS, 0xFD, &data, 1) ++ != CXD2880_RESULT_OK) { ++ dev_err(&priv->spi->dev, ++ "%s: read chip id failed.\n", __func__); ++ kfree(priv); ++ return NULL; ++ } ++ ++ chipid = (enum cxd2880_tnrdmd_chip_id)data; ++ if ((chipid != CXD2880_TNRDMD_CHIP_ID_CXD2880_ES1_0X) && ++ (chipid != CXD2880_TNRDMD_CHIP_ID_CXD2880_ES1_11)) { ++ dev_err(&priv->spi->dev, ++ "%s: chip id invalid.\n", __func__); ++ kfree(priv); ++ return NULL; ++ } ++ ++ fe->demodulator_priv = priv; ++ dev_info(&priv->spi->dev, ++ "CXD2880 driver version: Ver %s\n", ++ CXD2880_TNRDMD_DRIVER_VERSION); ++ ++ return fe; ++} ++EXPORT_SYMBOL(cxd2880_attach); ++ ++static struct dvb_frontend_ops cxd2880_dvbt_t2_ops = { ++ .info = { ++ .name = "Sony CXD2880", ++ .frequency_min = 174000000, ++ .frequency_max = 862000000, ++ .frequency_stepsize = 1000, ++ .caps = FE_CAN_INVERSION_AUTO | ++ FE_CAN_FEC_1_2 | ++ FE_CAN_FEC_2_3 | ++ FE_CAN_FEC_3_4 | ++ FE_CAN_FEC_4_5 | ++ FE_CAN_FEC_5_6 | ++ FE_CAN_FEC_7_8 | ++ FE_CAN_FEC_AUTO | ++ FE_CAN_QPSK | ++ FE_CAN_QAM_16 | ++ FE_CAN_QAM_32 | ++ FE_CAN_QAM_64 | ++ FE_CAN_QAM_128 | ++ FE_CAN_QAM_256 | ++ FE_CAN_QAM_AUTO | ++ FE_CAN_TRANSMISSION_MODE_AUTO | ++ FE_CAN_GUARD_INTERVAL_AUTO | ++ FE_CAN_2G_MODULATION | ++ FE_CAN_RECOVER | ++ FE_CAN_MUTE_TS, ++ }, ++ .delsys = { SYS_DVBT, SYS_DVBT2 }, ++ ++ .release = cxd2880_release, ++ .init = cxd2880_init, ++ .sleep = cxd2880_sleep, ++ .tune = cxd2880_tune, ++ .set_frontend = cxd2880_set_frontend, ++ .get_frontend = cxd2880_get_frontend, ++ .read_status = cxd2880_read_status, ++ .read_ber = cxd2880_read_ber, ++ .read_signal_strength = cxd2880_read_signal_strength, ++ .read_snr = cxd2880_read_snr, ++ .read_ucblocks = cxd2880_read_ucblocks, ++ .get_frontend_algo = cxd2880_get_frontend_algo, ++}; ++ ++MODULE_DESCRIPTION( ++"Sony CXD2880 DVB-T2/T tuner + demodulator drvier"); ++MODULE_AUTHOR("Sony Semiconductor Solutions Corporation"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/media/spi/Kconfig b/drivers/media/spi/Kconfig +index a21f5a39a440fe64a98f6bc04879fef65d753292..b07ac86fc53c782cf0980fc86f07d09bb5df0e40 100644 +--- a/drivers/media/spi/Kconfig ++++ b/drivers/media/spi/Kconfig +@@ -12,3 +12,17 @@ config VIDEO_GS1662 + endmenu + + endif ++ ++if SPI ++menu "Media SPI Adapters" ++ ++config CXD2880_SPI_DRV ++ tristate "Sony CXD2880 SPI support" ++ depends on DVB_CORE && SPI ++ default m if !MEDIA_SUBDRV_AUTOSELECT ++ help ++ Choose if you would like to have SPI interface support for Sony CXD2880. ++ ++endmenu ++ ++endif +diff --git a/drivers/media/spi/Makefile b/drivers/media/spi/Makefile +index ea64013d16cc7eda7424ed6684240e99b685e2cb..40e0f88d9f6c84a6ca6cfbd23d30102eabefd4e1 100644 +--- a/drivers/media/spi/Makefile ++++ b/drivers/media/spi/Makefile +@@ -1 +1,6 @@ + obj-$(CONFIG_VIDEO_GS1662) += gs1662.o ++obj-$(CONFIG_CXD2880_SPI_DRV) += cxd2880-spi.o ++ ++ccflags-y += -Idrivers/media/dvb-core ++ccflags-y += -Idrivers/media/dvb-frontends ++ccflags-y += -Idrivers/media/dvb-frontends/cxd2880 +\ No newline at end of file +diff --git a/drivers/media/spi/cxd2880-spi.c b/drivers/media/spi/cxd2880-spi.c +new file mode 100644 +index 0000000000000000000000000000000000000000..82e122349055be817eb74ed5bbcd7560485bc448 +--- /dev/null ++++ b/drivers/media/spi/cxd2880-spi.c +@@ -0,0 +1,728 @@ ++/* ++ * cxd2880-spi.c ++ * Sony CXD2880 DVB-T2/T tuner + demodulator driver ++ * SPI adapter ++ * ++ * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation ++ * ++ * 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; version 2 of the License. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#include ++ ++#include "dvb_demux.h" ++#include "dmxdev.h" ++#include "dvb_frontend.h" ++#include "cxd2880.h" ++ ++#define CXD2880_MAX_FILTER_SIZE 32 ++#define BURST_WRITE_MAX 128 ++#define MAX_TRANS_PACKET 300 ++ ++struct cxd2880_ts_buf_info { ++ u8 read_ready; ++ u8 almost_full; ++ u8 almost_empty; ++ u8 overflow; ++ u8 underflow; ++ u16 packet_num; ++}; ++ ++struct cxd2880_pid_config { ++ u8 is_enable; ++ u16 pid; ++}; ++ ++struct cxd2880_pid_filter_config { ++ u8 is_negative; ++ struct cxd2880_pid_config pid_config[CXD2880_MAX_FILTER_SIZE]; ++}; ++ ++struct cxd2880_dvb_spi { ++ struct dvb_frontend dvb_fe; ++ struct dvb_adapter adapter; ++ struct dvb_demux demux; ++ struct dmxdev dmxdev; ++ struct dmx_frontend dmx_fe; ++ struct task_struct *cxd2880_ts_read_thread; ++ struct spi_device *spi; ++ struct mutex spi_mutex; /* For SPI access exclusive control */ ++ int feed_count; ++ int all_pid_feed_count; ++ u8 *ts_buf; ++ struct cxd2880_pid_filter_config filter_config; ++}; ++ ++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); ++ ++static int cxd2880_write_spi(struct spi_device *spi, u8 *data, u32 size) ++{ ++ struct spi_message msg; ++ struct spi_transfer tx; ++ int ret = 0; ++ ++ if ((!spi) || (!data)) { ++ pr_err("%s: invalid arg\n", __func__); ++ return -EINVAL; ++ } ++ ++ memset(&tx, 0, sizeof(tx)); ++ tx.tx_buf = data; ++ tx.len = size; ++ ++ spi_message_init(&msg); ++ spi_message_add_tail(&tx, &msg); ++ ret = spi_sync(spi, &msg); ++ ++ return ret; ++} ++ ++static int cxd2880_write_reg(struct spi_device *spi, ++ u8 subAddress, const u8 *data, u32 size) ++{ ++ u8 send_data[BURST_WRITE_MAX + 4]; ++ const u8 *write_data_top = NULL; ++ int ret = 0; ++ ++ if ((!spi) || (!data)) { ++ pr_err("%s: invalid arg\n", __func__); ++ return -EINVAL; ++ } ++ if (size > BURST_WRITE_MAX) { ++ pr_err("%s: data size > WRITE_MAX\n", __func__); ++ return -EINVAL; ++ } ++ ++ if (subAddress + size > 0x100) { ++ pr_err("%s: out of range\n", __func__); ++ return -EINVAL; ++ } ++ ++ send_data[0] = 0x0E; ++ write_data_top = data; ++ ++ while (size > 0) { ++ send_data[1] = subAddress; ++ if (size > 255) ++ send_data[2] = 255; ++ else ++ send_data[2] = (u8)size; ++ ++ memcpy(&send_data[3], write_data_top, send_data[2]); ++ ++ ret = cxd2880_write_spi(spi, send_data, send_data[2] + 3); ++ if (ret) { ++ dev_err(&spi->dev, "%s: write spi failed %d\n", ++ __func__, ret); ++ break; ++ } ++ subAddress += send_data[2]; ++ write_data_top += send_data[2]; ++ size -= send_data[2]; ++ } ++ ++ return ret; ++} ++ ++static int cxd2880_spi_read_ts(struct spi_device *spi, ++ u8 *read_data, ++ u32 packet_num) ++{ ++ int ret = 0; ++ u8 data[3]; ++ struct spi_message message; ++ struct spi_transfer transfer[2]; ++ ++ if ((!spi) || (!read_data) || (!packet_num)) { ++ pr_err("%s: invalid arg\n", __func__); ++ return -EINVAL; ++ } ++ if (packet_num > 0xFFFF) { ++ dev_err(&spi->dev, "%s: packet num > 0xFFFF\n", __func__); ++ return -EINVAL; ++ } ++ ++ data[0] = 0x10; ++ data[1] = (u8)((packet_num >> 8) & 0xFF); ++ data[2] = (u8)(packet_num & 0xFF); ++ ++ spi_message_init(&message); ++ memset(transfer, 0, sizeof(transfer)); ++ ++ transfer[0].len = 3; ++ transfer[0].tx_buf = data; ++ spi_message_add_tail(&transfer[0], &message); ++ transfer[1].len = packet_num * 188; ++ transfer[1].rx_buf = read_data; ++ spi_message_add_tail(&transfer[1], &message); ++ ++ ret = spi_sync(spi, &message); ++ if (ret) ++ dev_err(&spi->dev, "%s: spi_write_then_read failed\n", ++ __func__); ++ ++ return ret; ++} ++ ++static int cxd2880_spi_read_ts_buffer_info(struct spi_device *spi, ++ struct cxd2880_ts_buf_info *info) ++{ ++ u8 send_data = 0x20; ++ u8 recv_data[2]; ++ int ret = 0; ++ ++ if ((!spi) || (!info)) { ++ pr_err("%s: invalid arg\n", __func__); ++ return -EINVAL; ++ } ++ ++ ret = spi_write_then_read(spi, &send_data, 1, ++ recv_data, sizeof(recv_data)); ++ if (ret) ++ dev_err(&spi->dev, ++ "%s: spi_write_then_read failed\n", __func__); ++ ++ info->read_ready = (u8)((recv_data[0] & 0x80) ? 1 : 0); ++ info->almost_full = (u8)((recv_data[0] & 0x40) ? 1 : 0); ++ info->almost_empty = (u8)((recv_data[0] & 0x20) ? 1 : 0); ++ info->overflow = (u8)((recv_data[0] & 0x10) ? 1 : 0); ++ info->underflow = (u8)((recv_data[0] & 0x08) ? 1 : 0); ++ info->packet_num = (u16)(((recv_data[0] & 0x07) << 8) | recv_data[1]); ++ ++ return ret; ++} ++ ++static int cxd2880_spi_clear_ts_buffer(struct spi_device *spi) ++{ ++ u8 data = 0x03; ++ int ret = 0; ++ ++ ret = cxd2880_write_spi(spi, &data, 1); ++ ++ if (ret) ++ pr_err("%s: write spi failed\n", __func__); ++ ++ return ret; ++} ++ ++static int cxd2880_set_pid_filter(struct spi_device *spi, ++ struct cxd2880_pid_filter_config *cfg) ++{ ++ u8 data[65]; ++ ++ if (!spi) { ++ pr_err("%s: ivnalid arg\n", __func__); ++ return -EINVAL; ++ } ++ ++ data[0] = 0x00; ++ if (cxd2880_write_reg(spi, 0x00, &data[0], 1) != 0) ++ return -EIO; ++ if (!cfg) { ++ data[0] = 0x02; ++ if (cxd2880_write_reg(spi, 0x50, &data[0], 1) != 0) ++ return -EIO; ++ } else { ++ data[0] = (u8)(cfg->is_negative ? 0x01 : 0x00); ++ { ++ int i = 0; ++ u16 pid = 0; ++ ++ for (i = 0; i < CXD2880_MAX_FILTER_SIZE; i++) { ++ pid = cfg->pid_config[i].pid; ++ if (cfg->pid_config[i].is_enable) { ++ data[1 + (i * 2)] = ++ (u8)((u8)(pid >> 8) | 0x20); ++ data[2 + (i * 2)] = ++ (u8)(pid & 0xFF); ++ } else { ++ data[1 + (i * 2)] = 0x00; ++ data[2 + (i * 2)] = 0x00; ++ } ++ } ++ } ++ if (cxd2880_write_reg(spi, 0x50, data, 65) != 0) ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static int cxd2880_update_pid_filter(struct cxd2880_dvb_spi *dvb_spi, ++ struct cxd2880_pid_filter_config *cfg, ++ bool is_all_pid_filter) ++{ ++ int ret = 0; ++ ++ if ((!dvb_spi) || (!cfg)) { ++ pr_err("%s: invalid arg.\n", __func__); ++ return -EINVAL; ++ } ++ ++ mutex_lock(&dvb_spi->spi_mutex); ++ if (is_all_pid_filter) { ++ struct cxd2880_pid_filter_config tmpcfg; ++ ++ memset(&tmpcfg, 0, sizeof(tmpcfg)); ++ tmpcfg.is_negative = 1; ++ tmpcfg.pid_config[0].is_enable = 1; ++ tmpcfg.pid_config[0].pid = 0x1FFF; ++ ++ ret = cxd2880_set_pid_filter(dvb_spi->spi, &tmpcfg); ++ } else { ++ ret = cxd2880_set_pid_filter(dvb_spi->spi, cfg); ++ } ++ mutex_unlock(&dvb_spi->spi_mutex); ++ ++ if (ret) { ++ dev_err(&dvb_spi->spi->dev, ++ "%s: set_pid_filter failed\n", __func__); ++ } ++ ++ return ret; ++} ++ ++static int cxd2880_ts_read(void *arg) ++{ ++ struct cxd2880_dvb_spi *dvb_spi = NULL; ++ struct cxd2880_ts_buf_info info; ++ struct timespec ts; ++ long elapsed = 0; ++ long starttime = 0; ++ u32 i; ++ int ret; ++ ++ dvb_spi = (struct cxd2880_dvb_spi *)arg; ++ if (!dvb_spi) { ++ pr_err("%s: invalid arg\n", __func__); ++ return -EINVAL; ++ } ++ ++ ret = cxd2880_spi_clear_ts_buffer(dvb_spi->spi); ++ if (ret) { ++ dev_err(&dvb_spi->spi->dev, ++ "%s: set_clear_ts_buffer failed\n", __func__); ++ return ret; ++ } ++ ++ getnstimeofday(&ts); ++ starttime = (ts.tv_sec * 1000) + (ts.tv_nsec / 1000000); ++ while (!kthread_should_stop()) { ++ getnstimeofday(&ts); ++ elapsed = ++ ((ts.tv_sec * 1000) + (ts.tv_nsec / 1000000)) ++ - starttime; ++ ret = cxd2880_spi_read_ts_buffer_info(dvb_spi->spi, ++ &info); ++ if (ret) { ++ pr_err("%s: spi_read_ts_buffer_info error\n", ++ __func__); ++ return ret; ++ } ++ ++ if (info.packet_num > MAX_TRANS_PACKET) { ++ for (i = 0; i < info.packet_num / MAX_TRANS_PACKET; ++ i++) { ++ cxd2880_spi_read_ts(dvb_spi->spi, ++ dvb_spi->ts_buf, ++ MAX_TRANS_PACKET); ++ dvb_dmx_swfilter(&dvb_spi->demux, ++ dvb_spi->ts_buf, ++ MAX_TRANS_PACKET * 188); ++ } ++ starttime = (ts.tv_sec * 1000) + (ts.tv_nsec / 1000000); ++ } else if ((info.packet_num > 0) && (elapsed >= 500)) { ++ cxd2880_spi_read_ts(dvb_spi->spi, ++ dvb_spi->ts_buf, ++ info.packet_num); ++ dvb_dmx_swfilter(&dvb_spi->demux, ++ dvb_spi->ts_buf, ++ info.packet_num * 188); ++ starttime = (ts.tv_sec * 1000) + (ts.tv_nsec / 1000000); ++ } else { ++ usleep_range(10000, 11000); ++ } ++ } ++ ++ return 0; ++} ++ ++static int cxd2880_start_feed(struct dvb_demux_feed *feed) ++{ ++ int ret = 0; ++ int i = 0; ++ struct dvb_demux *demux = NULL; ++ struct cxd2880_dvb_spi *dvb_spi = NULL; ++ ++ if (!feed) { ++ pr_err("%s: invalid arg\n", __func__); ++ return -EINVAL; ++ } ++ ++ demux = feed->demux; ++ if (!demux) { ++ pr_err("%s: feed->demux is NULL\n", __func__); ++ return -EINVAL; ++ } ++ dvb_spi = (struct cxd2880_dvb_spi *)demux->priv; ++ ++ if (dvb_spi->feed_count == CXD2880_MAX_FILTER_SIZE) { ++ dev_err(&dvb_spi->spi->dev, ++ "%s: Exceeded maximum PID count (32).", __func__); ++ dev_err(&dvb_spi->spi->dev, ++ "Selected PID cannot be enabled.\n"); ++ return -EBUSY; ++ } ++ ++ if (feed->pid == 0x2000) { ++ if (dvb_spi->all_pid_feed_count == 0) { ++ ret = cxd2880_update_pid_filter(dvb_spi, ++ &dvb_spi->filter_config, ++ true); ++ if (ret) { ++ dev_err(&dvb_spi->spi->dev, ++ "%s: update pid filter failed\n", ++ __func__); ++ return ret; ++ } ++ } ++ dvb_spi->all_pid_feed_count++; ++ ++ dev_dbg(&dvb_spi->spi->dev, ++ "%s: all PID feed (count = %d)\n", ++ __func__, dvb_spi->all_pid_feed_count); ++ } else { ++ struct cxd2880_pid_filter_config cfgtmp; ++ ++ cfgtmp = dvb_spi->filter_config; ++ ++ for (i = 0; i < CXD2880_MAX_FILTER_SIZE; i++) { ++ if (cfgtmp.pid_config[i].is_enable == 0) { ++ cfgtmp.pid_config[i].is_enable = 1; ++ cfgtmp.pid_config[i].pid = feed->pid; ++ dev_dbg(&dvb_spi->spi->dev, ++ "%s: store PID %d to #%d\n", ++ __func__, feed->pid, i); ++ break; ++ } ++ } ++ if (i == CXD2880_MAX_FILTER_SIZE) { ++ dev_err(&dvb_spi->spi->dev, ++ "%s: PID filter is full. Assumed bug.\n", ++ __func__); ++ return -EBUSY; ++ } ++ if (!dvb_spi->all_pid_feed_count) ++ ret = cxd2880_update_pid_filter(dvb_spi, ++ &cfgtmp, ++ false); ++ if (ret) ++ return ret; ++ ++ dvb_spi->filter_config = cfgtmp; ++ } ++ ++ if (dvb_spi->feed_count == 0) { ++ dvb_spi->ts_buf = ++ kmalloc(sizeof(u8) * MAX_TRANS_PACKET * 188, ++ GFP_KERNEL | GFP_DMA); ++ if (!dvb_spi->ts_buf) { ++ dev_err(&dvb_spi->spi->dev, ++ "%s: ts buffer allocate failed\n", __func__); ++ memset(&dvb_spi->filter_config, 0, ++ sizeof(dvb_spi->filter_config)); ++ dvb_spi->all_pid_feed_count = 0; ++ return -ENOMEM; ++ } ++ dvb_spi->cxd2880_ts_read_thread = kthread_run(cxd2880_ts_read, ++ dvb_spi, ++ "cxd2880_ts_read"); ++ if (IS_ERR(dvb_spi->cxd2880_ts_read_thread)) { ++ dev_err(&dvb_spi->spi->dev, ++ "%s: kthread_run failed/\n", ++ __func__); ++ kfree(dvb_spi->ts_buf); ++ dvb_spi->ts_buf = NULL; ++ memset(&dvb_spi->filter_config, 0, ++ sizeof(dvb_spi->filter_config)); ++ dvb_spi->all_pid_feed_count = 0; ++ return PTR_ERR(dvb_spi->cxd2880_ts_read_thread); ++ } ++ } ++ ++ dvb_spi->feed_count++; ++ ++ dev_dbg(&dvb_spi->spi->dev, "%s: start feed (count %d)\n", ++ __func__, dvb_spi->feed_count); ++ return 0; ++} ++ ++static int cxd2880_stop_feed(struct dvb_demux_feed *feed) ++{ ++ int i = 0; ++ int ret = 0; ++ struct dvb_demux *demux = NULL; ++ struct cxd2880_dvb_spi *dvb_spi = NULL; ++ ++ if (!feed) { ++ pr_err("%s: invalid arg\n", __func__); ++ return -EINVAL; ++ } ++ ++ demux = feed->demux; ++ if (!demux) { ++ pr_err("%s: feed->demux is NULL\n", __func__); ++ return -EINVAL; ++ } ++ dvb_spi = (struct cxd2880_dvb_spi *)demux->priv; ++ ++ if (!dvb_spi->feed_count) { ++ dev_warn(&dvb_spi->spi->dev, ++ "%s: no feed is started\n", __func__); ++ return -EINVAL; ++ } ++ ++ if (feed->pid == 0x2000) { ++ /* ++ * Special PID case. ++ * Number of 0x2000 feed request was stored ++ * in dvb_spi->all_pid_feed_count. ++ */ ++ if (dvb_spi->all_pid_feed_count <= 0) { ++ dev_warn(&dvb_spi->spi->dev, ++ "%s: PID %d not found.\n", ++ __func__, feed->pid); ++ return -EINVAL; ++ } ++ dvb_spi->all_pid_feed_count--; ++ } else { ++ struct cxd2880_pid_filter_config cfgtmp; ++ ++ cfgtmp = dvb_spi->filter_config; ++ ++ for (i = 0; i < CXD2880_MAX_FILTER_SIZE; i++) { ++ if (feed->pid == cfgtmp.pid_config[i].pid && ++ cfgtmp.pid_config[i].is_enable != 0) { ++ cfgtmp.pid_config[i].is_enable = 0; ++ cfgtmp.pid_config[i].pid = 0; ++ dev_dbg(&dvb_spi->spi->dev, ++ "%s: removed PID %d from #%d\n", ++ __func__, feed->pid, i); ++ break; ++ } ++ } ++ dvb_spi->filter_config = cfgtmp; ++ ++ if (i == CXD2880_MAX_FILTER_SIZE) { ++ dev_warn(&dvb_spi->spi->dev, "%s: PID %d not found\n", ++ __func__, feed->pid); ++ return -EINVAL; ++ } ++ } ++ ++ ret = cxd2880_update_pid_filter(dvb_spi, ++ &dvb_spi->filter_config, ++ dvb_spi->all_pid_feed_count > 0); ++ dvb_spi->feed_count--; ++ ++ if (dvb_spi->feed_count == 0) { ++ int ret_stop = 0; ++ ++ ret_stop = kthread_stop(dvb_spi->cxd2880_ts_read_thread); ++ if (ret_stop) { ++ dev_err(&dvb_spi->spi->dev, ++ "%s: cxd2880_ts_read thread didn't terminate normally\n", ++ __func__); ++ ret = ret_stop; ++ } ++ kfree(dvb_spi->ts_buf); ++ dvb_spi->ts_buf = NULL; ++ } ++ ++ dev_dbg(&dvb_spi->spi->dev, "%s: stop feed ok.(count %d)\n", ++ __func__, dvb_spi->feed_count); ++ ++ return ret; ++} ++ ++static const struct of_device_id cxd2880_spi_of_match[] = { ++ { .compatible = "sony,cxd2880" }, ++ { /* sentinel */ } ++}; ++ ++MODULE_DEVICE_TABLE(of, cxd2880_spi_of_match); ++ ++static int ++cxd2880_spi_probe(struct spi_device *spi) ++{ ++ int ret = 0; ++ struct cxd2880_dvb_spi *dvb_spi = NULL; ++ struct cxd2880_config config; ++ ++ if (!spi) { ++ pr_err("%s: invalid arg.\n", __func__); ++ return -EINVAL; ++ } ++ ++ dvb_spi = kzalloc(sizeof(struct cxd2880_dvb_spi), GFP_KERNEL); ++ if (!dvb_spi) ++ return -ENOMEM; ++ ++ dvb_spi->spi = spi; ++ mutex_init(&dvb_spi->spi_mutex); ++ dev_set_drvdata(&spi->dev, dvb_spi); ++ config.spi = spi; ++ config.spi_mutex = &dvb_spi->spi_mutex; ++ ++ ret = dvb_register_adapter(&dvb_spi->adapter, ++ "CXD2880", ++ THIS_MODULE, ++ &spi->dev, ++ adapter_nr); ++ if (ret < 0) { ++ dev_err(&spi->dev, "%s: dvb_register_adapter() failed\n", ++ __func__); ++ goto fail_adapter; ++ } ++ ++ if (!dvb_attach(cxd2880_attach, &dvb_spi->dvb_fe, &config)) { ++ dev_err(&spi->dev, "%s: cxd2880_attach failed\n", __func__); ++ goto fail_attach; ++ } ++ ++ ret = dvb_register_frontend(&dvb_spi->adapter, ++ &dvb_spi->dvb_fe); ++ if (ret < 0) { ++ dev_err(&spi->dev, "%s: dvb_register_frontend() failed\n", ++ __func__); ++ goto fail_frontend; ++ } ++ ++ dvb_spi->demux.dmx.capabilities = DMX_TS_FILTERING; ++ dvb_spi->demux.priv = dvb_spi; ++ dvb_spi->demux.filternum = CXD2880_MAX_FILTER_SIZE; ++ dvb_spi->demux.feednum = CXD2880_MAX_FILTER_SIZE; ++ dvb_spi->demux.start_feed = cxd2880_start_feed; ++ dvb_spi->demux.stop_feed = cxd2880_stop_feed; ++ ++ ret = dvb_dmx_init(&dvb_spi->demux); ++ if (ret < 0) { ++ dev_err(&spi->dev, "%s: dvb_dmx_init() failed\n", __func__); ++ goto fail_dmx; ++ } ++ ++ dvb_spi->dmxdev.filternum = CXD2880_MAX_FILTER_SIZE; ++ dvb_spi->dmxdev.demux = &dvb_spi->demux.dmx; ++ dvb_spi->dmxdev.capabilities = 0; ++ ret = dvb_dmxdev_init(&dvb_spi->dmxdev, ++ &dvb_spi->adapter); ++ if (ret < 0) { ++ dev_err(&spi->dev, "%s: dvb_dmxdev_init() failed\n", __func__); ++ goto fail_dmxdev; ++ } ++ ++ dvb_spi->dmx_fe.source = DMX_FRONTEND_0; ++ ret = dvb_spi->demux.dmx.add_frontend(&dvb_spi->demux.dmx, ++ &dvb_spi->dmx_fe); ++ if (ret < 0) { ++ dev_err(&spi->dev, "%s: add_frontend() failed\n", __func__); ++ goto fail_dmx_fe; ++ } ++ ++ ret = dvb_spi->demux.dmx.connect_frontend(&dvb_spi->demux.dmx, ++ &dvb_spi->dmx_fe); ++ if (ret < 0) { ++ dev_err(&spi->dev, "%s: dvb_register_frontend() failed\n", ++ __func__); ++ goto fail_fe_conn; ++ } ++ ++ dev_info(&spi->dev, "Sony CXD2880 has successfully attached.\n"); ++ ++ return 0; ++ ++fail_fe_conn: ++ dvb_spi->demux.dmx.remove_frontend(&dvb_spi->demux.dmx, ++ &dvb_spi->dmx_fe); ++fail_dmx_fe: ++ dvb_dmxdev_release(&dvb_spi->dmxdev); ++fail_dmxdev: ++ dvb_dmx_release(&dvb_spi->demux); ++fail_dmx: ++ dvb_unregister_frontend(&dvb_spi->dvb_fe); ++fail_frontend: ++ dvb_frontend_detach(&dvb_spi->dvb_fe); ++fail_attach: ++ dvb_unregister_adapter(&dvb_spi->adapter); ++fail_adapter: ++ kfree(dvb_spi); ++ return ret; ++} ++ ++static int ++cxd2880_spi_remove(struct spi_device *spi) ++{ ++ struct cxd2880_dvb_spi *dvb_spi; ++ ++ if (!spi) { ++ pr_err("%s: invalid arg\n", __func__); ++ return -EINVAL; ++ } ++ ++ dvb_spi = (struct cxd2880_dvb_spi *)dev_get_drvdata(&spi->dev); ++ ++ if (!dvb_spi) { ++ pr_err("%s: failed\n", __func__); ++ return -EINVAL; ++ } ++ dvb_spi->demux.dmx.remove_frontend(&dvb_spi->demux.dmx, ++ &dvb_spi->dmx_fe); ++ dvb_dmxdev_release(&dvb_spi->dmxdev); ++ dvb_dmx_release(&dvb_spi->demux); ++ dvb_unregister_frontend(&dvb_spi->dvb_fe); ++ dvb_frontend_detach(&dvb_spi->dvb_fe); ++ dvb_unregister_adapter(&dvb_spi->adapter); ++ ++ kfree(dvb_spi); ++ dev_info(&spi->dev, "%s: cxd2880_spi remove ok.\n", __func__); ++ ++ return 0; ++} ++ ++static const struct spi_device_id cxd2880_spi_id[] = { ++ { "cxd2880", 0 }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(spi, cxd2880_spi_id); ++ ++static struct spi_driver cxd2880_spi_driver = { ++ .driver = { ++ .name = "cxd2880", ++ .of_match_table = cxd2880_spi_of_match, ++ }, ++ .id_table = cxd2880_spi_id, ++ .probe = cxd2880_spi_probe, ++ .remove = cxd2880_spi_remove, ++}; ++module_spi_driver(cxd2880_spi_driver); ++ ++MODULE_DESCRIPTION( ++"Sony CXD2880 DVB-T2/T tuner + demodulator drvier SPI adapter"); ++MODULE_AUTHOR("Sony Semiconductor Solutions Corporation"); ++MODULE_LICENSE("GPL v2"); + +From 4337bdbae5d782bdc4a7f361a19b455b02e83a30 Mon Sep 17 00:00:00 2001 +From: Yasunari Takiguchi +Date: Thu, 22 Dec 2016 15:34:12 +0900 +Subject: [PATCH 207/207] BCM2708: Add Raspberry Pi TV HAT Device Tree Support + +This is an EXAMPLE CODE of Raspberry Pi TV HAT device tree overlay. +Although this is not a part of our release code, it has been used to verify +CXD2880 device driver with TV HAT. + +Add the following line to /boot/config.txt to enable TV HAT: + +dtoverlay=rpi-tv + +Reboot Raspberry Pi and check the existance of /proc/device-tree/soc/spi@7e204000/cxd2880@0. +If exists, the installation is successful. you should be able to find the following three files. +/dev/dvb/adapter0/frontend0 +/dev/dvb/adapter0/demux0 +/dev/dvb/adapter0/dvr0 + +Signed-off-by: Yasunari Takiguchi +Signed-off-by: Masayuki Yamamoto +Signed-off-by: Hideki Nozawa +Signed-off-by: Kota Yonezawa +Signed-off-by: Toshihiko Matsumoto +Signed-off-by: Satoshi Watanabe +--- + arch/arm/boot/dts/overlays/Makefile | 1 + + arch/arm/boot/dts/overlays/README | 6 ++++++ + arch/arm/boot/dts/overlays/rpi-tv-overlay.dts | 31 +++++++++++++++++++++++++++ + 3 files changed, 38 insertions(+) + create mode 100644 arch/arm/boot/dts/overlays/rpi-tv-overlay.dts + +diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile +index b64dd7ac0630b2b525809a9f5221420f34a58ac9..e2f66a55dc5afe13d690c2c17827054ac94b7168 100644 +--- a/arch/arm/boot/dts/overlays/Makefile ++++ b/arch/arm/boot/dts/overlays/Makefile +@@ -81,6 +81,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + rpi-ft5406.dtbo \ + rpi-proto.dtbo \ + rpi-sense.dtbo \ ++ rpi-tv.dtbo \ + rra-digidac1-wm8741-audio.dtbo \ + sc16is750-i2c.dtbo \ + sc16is752-spi1.dtbo \ +diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README +index 1377e5b8e8363c3e0ede318ce54bd784cb70d4c9..e2a803e5180cf78d67b6723cfd2f6d3b2b54e53b 100644 +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -1142,6 +1142,12 @@ Load: dtoverlay=rpi-sense + Params: + + ++Name: rpi-tv ++Info: Raspberry Pi TV HAT ++Load: dtoverlay=rpi-tv ++Params: ++ ++ + Name: rra-digidac1-wm8741-audio + Info: Configures the Red Rocks Audio DigiDAC1 soundcard + Load: dtoverlay=rra-digidac1-wm8741-audio +diff --git a/arch/arm/boot/dts/overlays/rpi-tv-overlay.dts b/arch/arm/boot/dts/overlays/rpi-tv-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..a68f6f793d8efd8b2e2adf9f2fb6426f61ff464a +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/rpi-tv-overlay.dts +@@ -0,0 +1,31 @@ ++// rpi-tv HAT ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ status = "okay"; ++ ++ spidev@0 { ++ status = "disabled"; ++ }; ++ ++ cxd2880@0 { ++ compatible = "sony,cxd2880"; ++ reg = <0>; /* CE0 */ ++ spi-max-frequency = <50000000>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++};